Documentation
¶
Index ¶
- Constants
- func DeletedVolumesPath(dataPath string) string
- func EnsureLbdDevices(log *slog.Logger) error
- func EnsureLoopDevices(log *slog.Logger) error
- func LoopDeviceAvailable() bool
- func SaveDeletedVolumeMetadata(dir string, meta *DeletedVolumeMetadata) error
- type ActiveMount
- type CloudDiskClient
- type CloudSegmentUploader
- type CloudUpdatesClient
- type CloudVolumeRegistrar
- type DeletedVolumeEntry
- type DeletedVolumeGC
- type DeletedVolumeGCConfig
- type DeletedVolumeGCResult
- type DeletedVolumeMetadata
- type DiskMountController
- func (c *DiskMountController) Index() entity.Attr
- func (c *DiskMountController) Init(ctx context.Context) error
- func (c *DiskMountController) Reconcile(ctx context.Context, mount *storage_v1alpha.DiskMount, meta *entity.Meta) error
- func (c *DiskMountController) ReconcileOrphanMounts(ctx context.Context, minMountAge time.Duration) error
- func (c *DiskMountController) ReconcileWithEntities(ctx context.Context) error
- func (c *DiskMountController) RestoreImageIfMissing(ctx context.Context, volState *VolumeState, imagePath string) error
- func (c *DiskMountController) SetCloudClient(client CloudDiskClient)
- func (c *DiskMountController) SetEAC(eac *entityserver_v1alpha.EntityAccessClient)
- func (c *DiskMountController) SetKeepMounts(v bool)
- func (c *DiskMountController) SetUpdatesClient(client CloudUpdatesClient)
- func (c *DiskMountController) SetWriteTracker(wt writeTracker)
- func (c *DiskMountController) Shutdown()
- type DiskMountOps
- type DiskVolumeController
- func (c *DiskVolumeController) Index() entity.Attr
- func (c *DiskVolumeController) Init(ctx context.Context) error
- func (c *DiskVolumeController) Reconcile(ctx context.Context, volume *storage_v1alpha.DiskVolume, meta *entity.Meta) error
- func (c *DiskVolumeController) ReconcileWithEntities(ctx context.Context) error
- func (c *DiskVolumeController) SetCloudVolumeRegistrar(registrar CloudVolumeRegistrar, clusterID string)
- func (c *DiskVolumeController) SetEAC(eac *entityserver_v1alpha.EntityAccessClient)
- func (c *DiskVolumeController) SetKeepMounts(v bool)
- func (c *DiskVolumeController) SetUpdatesClient(client CloudUpdatesClient)
- func (c *DiskVolumeController) Shutdown()
- type DiskVolumeOps
- type ImageSnapshotter
- type ListOptions
- type LogSegmentInfo
- type LogSegmentUploader
- type LogWatcher
- type MountState
- type RegisterVolumeRequest
- type SnapshotRequest
- type State
- func (s *State) DeleteMount(entityId string)
- func (s *State) DeleteMountAndSave(entityId string) error
- func (s *State) DeleteVolume(entityId string)
- func (s *State) DeleteVolumeAndSave(entityId string) error
- func (s *State) GetMount(entityId string) *MountState
- func (s *State) GetVolume(entityId string) *VolumeState
- func (s *State) GetVolumeByVolumeId(volumeId string) *VolumeState
- func (s *State) LeaseNonceForCloudVolume(cloudVolumeId string) string
- func (s *State) ListMounts() []*MountState
- func (s *State) ListVolumes() []*VolumeState
- func (s *State) Save() error
- func (s *State) SetCloudVolumeId(entityId, cloudVolumeId string) error
- func (s *State) SetMount(entityId string, mount *MountState)
- func (s *State) SetMountAndSave(entityId string, mount *MountState) error
- func (s *State) SetMountFromVolume(volumeId string, mount *MountState) (devicePath, mountPath string, err error)
- func (s *State) SetPath(dataPath string)
- func (s *State) SetVolume(entityId string, volume *VolumeState)
- func (s *State) SetVolumeAndSave(entityId string, volume *VolumeState) error
- type UpdateInfo
- type UpdateKind
- type UploadRequest
- type VolumeState
Constants ¶
const OrphanMountSweepGracePeriod = 2 * time.Minute
OrphanMountSweepGracePeriod is how old a disk_mount must be before the orphan sweeper will delete it for a missing backing volume. It guards against a race where a mount has just been created but its volume entity hasn't been observed yet.
Variables ¶
This section is empty.
Functions ¶
func DeletedVolumesPath ¶ added in v0.7.0
DeletedVolumesPath returns the path to the deleted-volumes directory.
func EnsureLbdDevices ¶
EnsureLbdDevices checks if the lbd kernel module and lbdctl are available.
func EnsureLoopDevices ¶
EnsureLoopDevices ensures /dev/loop-control and loop device nodes are available. In containers, /dev may be a fresh mount that doesn't include loop devices even when the kernel supports them. This function creates the device nodes via mknod if they're missing.
func LoopDeviceAvailable ¶
func LoopDeviceAvailable() bool
LoopDeviceAvailable checks if loop devices can be used.
func SaveDeletedVolumeMetadata ¶ added in v0.7.0
func SaveDeletedVolumeMetadata(dir string, meta *DeletedVolumeMetadata) error
SaveDeletedVolumeMetadata writes metadata to a JSON file inside the given directory.
Types ¶
type ActiveMount ¶
ActiveMount describes a mount found on the running system.
type CloudDiskClient ¶
type CloudDiskClient interface {
AcquireLease(ctx context.Context, volumeID string) (nonce string, err error)
ReleaseLease(ctx context.Context, volumeID string, nonce string) error
// ListLogSegments returns the volume's log segments whose TAI64N label
// sorts after `after`. Passing the caller's replay horizon keeps the server
// from walking, and returning, a volume's entire backup history. An empty
// `after` asks for everything.
ListLogSegments(ctx context.Context, volumeID string, after string) ([]LogSegmentInfo, error)
DownloadLogSegment(ctx context.Context, volumeID, segmentID string) (io.ReadCloser, error)
}
CloudDiskClient abstracts the cloud operations needed by the mount controller for volume lease management and log segment retrieval.
func NewCloudDiskClient ¶
func NewCloudDiskClient(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient) CloudDiskClient
NewCloudDiskClient creates a new CloudDiskClient.
func NewCloudDiskClientWithUpdates ¶ added in v0.14.0
func NewCloudDiskClientWithUpdates(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient, updates CloudUpdatesClient) CloudDiskClient
NewCloudDiskClientWithUpdates builds a disk client over an existing updates client, so callers that already have one need not construct a second.
type CloudSegmentUploader ¶
type CloudSegmentUploader struct {
// contains filtered or unexported fields
}
CloudSegmentUploader implements LogSegmentUploader by uploading lbd log segments to miren.cloud as lbd_log volume updates.
A segment's TAI64N label becomes the update's ordering key, which is what replay sorts and horizon-compares on.
func NewCloudSegmentUploader ¶
func NewCloudSegmentUploader(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient, state *State) *CloudSegmentUploader
func NewCloudSegmentUploaderWithClient ¶ added in v0.14.0
func NewCloudSegmentUploaderWithClient(log *slog.Logger, updates CloudUpdatesClient, state *State) *CloudSegmentUploader
NewCloudSegmentUploaderWithClient builds an uploader over an existing updates client, so callers that already have one need not construct a second.
func (*CloudSegmentUploader) UploadSegment ¶
func (u *CloudSegmentUploader) UploadSegment(ctx context.Context, volumeID, segmentPath string) (string, error)
UploadSegment uploads a log segment file to the cloud and returns the cloud segment ID.
type CloudUpdatesClient ¶ added in v0.14.0
type CloudUpdatesClient interface {
// Upload sends one update and returns the cloud's ID for it. size must be
// the exact byte length of body.
Upload(ctx context.Context, volumeID string, req UploadRequest, body io.Reader, size int64) (string, error)
// List returns a volume's active updates in replay order.
List(ctx context.Context, volumeID string, opts ListOptions) ([]UpdateInfo, error)
// Download opens an update's payload. The caller closes it.
Download(ctx context.Context, volumeID, updateID string) (io.ReadCloser, error)
}
CloudUpdatesClient is the runtime's view of the cloud's volume update API.
func NewCloudUpdatesClient ¶ added in v0.14.0
func NewCloudUpdatesClient(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient) CloudUpdatesClient
NewCloudUpdatesClient creates a client for the cloud's volume update API.
type CloudVolumeRegistrar ¶ added in v0.14.0
type CloudVolumeRegistrar interface {
// EnsureVolume registers the volume and returns its cloud identifier. It is
// safe to call repeatedly: the same local volume always resolves to the
// same cloud volume.
EnsureVolume(ctx context.Context, req RegisterVolumeRequest) (string, error)
}
CloudVolumeRegistrar creates a volume in miren.cloud for a local disk, so the backup paths have something to address.
Without this a volume only exists on the node, and every cloud call carries a local id the cloud has never heard of.
func NewCloudVolumeRegistrar ¶ added in v0.14.0
func NewCloudVolumeRegistrar(log *slog.Logger, baseURL string, authClient *cloudauth.AuthClient) CloudVolumeRegistrar
NewCloudVolumeRegistrar creates a registrar against the given cloud.
type DeletedVolumeEntry ¶ added in v0.7.0
type DeletedVolumeEntry struct {
Metadata *DeletedVolumeMetadata
Path string
}
DeletedVolumeEntry combines metadata with its directory path.
func ListDeletedVolumes ¶ added in v0.7.0
func ListDeletedVolumes(dataPath string) ([]DeletedVolumeEntry, error)
ListDeletedVolumes scans the deleted-volumes directory and returns all entries with valid metadata.
type DeletedVolumeGC ¶ added in v0.7.0
type DeletedVolumeGC struct {
Log *slog.Logger
DataPath string
Config DeletedVolumeGCConfig
// contains filtered or unexported fields
}
DeletedVolumeGC periodically purges soft-deleted disk volumes that have exceeded the retention period.
func (*DeletedVolumeGC) RunGC ¶ added in v0.7.0
func (g *DeletedVolumeGC) RunGC() (*DeletedVolumeGCResult, error)
RunGC scans the deleted-volumes directory and removes entries that have exceeded the retention period.
func (*DeletedVolumeGC) Start ¶ added in v0.7.0
func (g *DeletedVolumeGC) Start(ctx context.Context)
Start begins the periodic GC process.
func (*DeletedVolumeGC) Stop ¶ added in v0.7.0
func (g *DeletedVolumeGC) Stop()
Stop gracefully stops the controller.
type DeletedVolumeGCConfig ¶ added in v0.7.0
DeletedVolumeGCConfig holds configuration for deleted volume garbage collection.
func DefaultDeletedVolumeGCConfig ¶ added in v0.7.0
func DefaultDeletedVolumeGCConfig() DeletedVolumeGCConfig
DefaultDeletedVolumeGCConfig returns the default GC configuration.
type DeletedVolumeGCResult ¶ added in v0.7.0
DeletedVolumeGCResult contains information about volumes processed during GC.
type DeletedVolumeMetadata ¶ added in v0.7.0
type DeletedVolumeMetadata struct {
DiskID string `json:"disk_id"`
DiskName string `json:"disk_name"`
SizeGb int64 `json:"size_gb"`
Filesystem string `json:"filesystem"`
VolumeID string `json:"volume_id"`
VolumeMode string `json:"volume_mode"`
CreatedBy string `json:"created_by,omitempty"`
NodeID compute.NodeId `json:"node_id"`
DeletedAt time.Time `json:"deleted_at"`
}
DeletedVolumeMetadata stores information about a soft-deleted disk volume so it can be restored via the undelete command.
func LoadDeletedVolumeMetadata ¶ added in v0.7.0
func LoadDeletedVolumeMetadata(dir string) (*DeletedVolumeMetadata, error)
LoadDeletedVolumeMetadata reads metadata from a JSON file inside the given directory.
type DiskMountController ¶
type DiskMountController struct {
// contains filtered or unexported fields
}
DiskMountController watches disk_mount entities and manages loop-device mounts.
func NewDiskMountController ¶
func NewDiskMountController(log *slog.Logger, dataPath string, nodeId compute.NodeId, state *State, ops DiskMountOps) *DiskMountController
func (*DiskMountController) Index ¶
func (c *DiskMountController) Index() entity.Attr
func (*DiskMountController) Reconcile ¶
func (c *DiskMountController) Reconcile(ctx context.Context, mount *storage_v1alpha.DiskMount, meta *entity.Meta) error
func (*DiskMountController) ReconcileOrphanMounts ¶ added in v0.12.0
func (c *DiskMountController) ReconcileOrphanMounts(ctx context.Context, minMountAge time.Duration) error
ReconcileOrphanMounts deletes disk_mount entities on this node whose backing disk_volume no longer exists. Such a mount can never reach its desired state and, before writes are deduped, self-retriggers reconcile indefinitely (MIR-1345). Deleting the entity via the entity server also removes its secondary-index keys, which a raw etcd delete would leave dangling.
minMountAge guards against deleting a just-created mount whose volume entity hasn't been observed yet; pass OrphanMountSweepGracePeriod in production.
func (*DiskMountController) ReconcileWithEntities ¶
func (c *DiskMountController) ReconcileWithEntities(ctx context.Context) error
ReconcileWithEntities reconciles local state with entity server
func (*DiskMountController) RestoreImageIfMissing ¶ added in v0.14.0
func (c *DiskMountController) RestoreImageIfMissing(ctx context.Context, volState *VolumeState, imagePath string) error
RestoreImageIfMissing rebuilds a universal-mode volume's backing image from the newest loop_image snapshot in the cloud, when the host no longer has one.
Universal volumes are mounted by the volume controller rather than the mount controller, so this wrapper exists for the accelerator-shaped path and for callers that already hold a mount controller; the volume controller has its own.
func (*DiskMountController) SetCloudClient ¶
func (c *DiskMountController) SetCloudClient(client CloudDiskClient)
SetCloudClient sets the cloud client for lease management and segment replay.
func (*DiskMountController) SetEAC ¶
func (c *DiskMountController) SetEAC(eac *entityserver_v1alpha.EntityAccessClient)
func (*DiskMountController) SetKeepMounts ¶
func (c *DiskMountController) SetKeepMounts(v bool)
SetKeepMounts tells the controller to skip unmounting during Shutdown. Used during reload so the replacement process inherits the mounts.
func (*DiskMountController) SetUpdatesClient ¶ added in v0.14.0
func (c *DiskMountController) SetUpdatesClient(client CloudUpdatesClient)
SetUpdatesClient wires the generic volume update client, used to recover a universal-mode volume's backing image from the cloud.
func (*DiskMountController) SetWriteTracker ¶ added in v0.12.0
func (c *DiskMountController) SetWriteTracker(wt writeTracker)
SetWriteTracker wires the reconcile controller's write tracker so that entity writes this controller makes directly (via updateMountState) are recorded and their watch events are skipped, preventing a self-retriggering reconcile loop.
func (*DiskMountController) Shutdown ¶
func (c *DiskMountController) Shutdown()
Shutdown releases cloud leases. Mount/detach cleanup is handled by DiskVolumeController.Shutdown which owns all mount lifecycle. If keepMounts is set (reload), everything is skipped.
type DiskMountOps ¶
type DiskMountOps interface {
CreateDir(path string, perm os.FileMode) error
LoopAttach(imagePath string) (devicePath string, err error)
LoopDetach(devicePath string) error
// FindLoopByBacking returns the loop device path (e.g. /dev/loop3) currently
// backing the given image file, or "" if no loop device is attached to it.
// Used to detect stale/double attachments of the same disk image.
FindLoopByBacking(imagePath string) (devicePath string, err error)
// FindAllLoopBackings returns a map of loop device path to the backing
// file currently attached to it, for every loop device in the kernel.
// Used by boot-time orphan reconciliation to find stale attachments.
FindAllLoopBackings() (map[string]string, error)
LbdAttach(ctx context.Context, imagePath, logDir string) (devicePath string, err error)
LbdDetach(ctx context.Context, devicePath string) error
Mount(device, mountPath, filesystem string, readOnly bool) error
Unmount(path string) error
IsMounted(path string) bool
// IsDeviceMounted reports whether device is currently mounted at any
// path in the kernel mount table. Used as a safety check before
// running fsck, which must never run against a live filesystem.
// Returns an error if the mount table cannot be read — callers must
// treat that as "unknown" and refuse the destructive operation they
// were gating on this check.
IsDeviceMounted(device string) (bool, error)
IsFormatted(ctx context.Context, device, filesystem string) (bool, error)
FormatDevice(ctx context.Context, device, filesystem string) error
// Fsck runs a filesystem check-and-repair on device. The device must
// not be mounted anywhere when this is called. Used to recover from
// EUCLEAN ("Structure needs cleaning") mount failures after an
// unclean shutdown.
Fsck(ctx context.Context, device, filesystem string) error
// FindMounts returns all mounts whose mount path starts with the given prefix.
FindMounts(pathPrefix string) []ActiveMount
}
DiskMountOps abstracts OS operations for disk mount management. This interface enables testing without requiring actual loop device or mount operations.
func NewRealDiskMountOps ¶
func NewRealDiskMountOps(log *slog.Logger) DiskMountOps
type DiskVolumeController ¶
type DiskVolumeController struct {
// contains filtered or unexported fields
}
DiskVolumeController watches disk_volume entities and manages sparse disk images using loop devices.
func NewDiskVolumeController ¶
func NewDiskVolumeController(log *slog.Logger, dataPath string, nodeId compute.NodeId, state *State, ops DiskVolumeOps, mntOps DiskMountOps) *DiskVolumeController
func (*DiskVolumeController) Index ¶
func (c *DiskVolumeController) Index() entity.Attr
func (*DiskVolumeController) Reconcile ¶
func (c *DiskVolumeController) Reconcile(ctx context.Context, volume *storage_v1alpha.DiskVolume, meta *entity.Meta) error
func (*DiskVolumeController) ReconcileWithEntities ¶
func (c *DiskVolumeController) ReconcileWithEntities(ctx context.Context) error
ReconcileWithEntities reconciles local state with entity server
func (*DiskVolumeController) SetCloudVolumeRegistrar ¶ added in v0.14.0
func (c *DiskVolumeController) SetCloudVolumeRegistrar(registrar CloudVolumeRegistrar, clusterID string)
SetCloudVolumeRegistrar wires cloud registration. Without it, volumes are created locally and never appear in miren.cloud.
func (*DiskVolumeController) SetEAC ¶
func (c *DiskVolumeController) SetEAC(eac *entityserver_v1alpha.EntityAccessClient)
func (*DiskVolumeController) SetKeepMounts ¶
func (c *DiskVolumeController) SetKeepMounts(v bool)
SetKeepMounts tells the controller to skip unmounting during Shutdown. Used during reload so the replacement process inherits the mounts.
func (*DiskVolumeController) SetUpdatesClient ¶ added in v0.14.0
func (c *DiskVolumeController) SetUpdatesClient(client CloudUpdatesClient)
SetUpdatesClient wires the client used to restore a missing backing image.
func (*DiskVolumeController) Shutdown ¶
func (c *DiskVolumeController) Shutdown()
Shutdown unmounts all disk volumes and detaches their backing devices. It uses the actual kernel mount table rather than trusting persisted state, finding all mounts under diskMountBasePath and tearing them down. If keepMounts is set (reload), everything is left in place for the new process.
type DiskVolumeOps ¶
type DiskVolumeOps interface {
CreateVolumeDir(path string) error
RemoveVolumeDir(path string) error
MoveVolumeDir(src, dst string) error
VolumePathExists(path string) bool
CreateDiskImage(path string, sizeBytes int64) error
}
DiskVolumeOps abstracts OS operations for disk volume management. This interface enables testing without requiring actual filesystem operations.
func NewRealDiskVolumeOps ¶
func NewRealDiskVolumeOps(log *slog.Logger) DiskVolumeOps
type ImageSnapshotter ¶ added in v0.14.0
type ImageSnapshotter struct {
// contains filtered or unexported fields
}
ImageSnapshotter uploads a compressed snapshot of a universal-mode volume's backing image to the cloud as a loop_image update.
This is deliberately on demand only. Snapshotting a mounted, actively-written image means reading a file while its single writer -- the loop device -- keeps changing it, so the head and tail of the read come from different moments. The result is not crash-consistent; it is a state that never existed on the disk at any instant, which a journalling filesystem and Postgres's WAL are both entitled to be confused by. Taking that automatically on a timer and filing the result as a restore point would be worse than not backing up at all, because it looks like protection.
So the decision that it is safe -- the disk is idle, or unmounted, or the operator accepts the risk -- belongs to a person, not a ticker. Accelerator mode is the answer for continuous backup: lbd captures writes in order inside the kernel, so its log segments cannot smear.
func NewImageSnapshotter ¶ added in v0.14.0
func NewImageSnapshotter(log *slog.Logger, updates CloudUpdatesClient) *ImageSnapshotter
NewImageSnapshotter creates a snapshotter over the given updates client.
func (*ImageSnapshotter) Snapshot ¶ added in v0.14.0
func (s *ImageSnapshotter) Snapshot(ctx context.Context, req SnapshotRequest) (string, error)
Snapshot compresses the image and uploads it, returning the cloud's update ID.
type ListOptions ¶ added in v0.14.0
type ListOptions struct {
Kind UpdateKind
After string
Until string
// Descending returns newest first instead of replay order. Paired with
// Limit 1 it answers "what is the most recent update" in one round trip,
// rather than paging a volume's whole history to keep the last row.
Descending bool
// Limit caps how many updates come back. Zero walks every page, which is
// what replay wants; a positive value stops as soon as it has enough.
Limit int
}
ListOptions filters a volume's update stream.
After is exclusive and must be paired with a Kind: ordering keys are only comparable within one kind, so the cloud refuses the pair otherwise.
type LogSegmentInfo ¶
LogSegmentInfo describes a remote log segment with its cloud ID and TAI64N label.
type LogSegmentUploader ¶
type LogSegmentUploader interface {
// UploadSegment uploads a log segment and returns the cloud segment ID.
UploadSegment(ctx context.Context, volumeID, segmentPath string) (segmentID string, err error)
}
LogSegmentUploader uploads completed log segments to cloud storage.
type LogWatcher ¶
type LogWatcher struct {
// contains filtered or unexported fields
}
LogWatcher monitors accelerator volume log directories for completed segments. When an uploader is configured, segments are uploaded then removed. When no uploader is configured (cloud not available), segments are simply deleted.
func NewLogWatcher ¶
func NewLogWatcher(log *slog.Logger, state *State, uploader LogSegmentUploader, interval time.Duration) *LogWatcher
NewLogWatcher creates a new LogWatcher that scans at the given interval. Pass nil for uploader to just delete logs without uploading.
func (*LogWatcher) Run ¶
func (w *LogWatcher) Run(ctx context.Context) error
Run starts the log watcher loop. It blocks until the context is cancelled.
func (*LogWatcher) Wait ¶
func (w *LogWatcher) Wait()
Wait blocks until the watcher's Run method has returned.
type MountState ¶
type MountState struct {
// EntityId is the ID of the disk_mount entity
EntityId string `json:"entity_id"`
// VolumeId is the ID of the disk_volume entity
VolumeId string `json:"volume_id"`
// CloudVolumeId is the backing volume's miren.cloud identifier, captured
// when the mount is created. Every cloud lease call keys off it, and
// recording it here means lease release still works after the volume's
// VolumeState is gone (e.g. orphan cleanup). Empty for mounts persisted
// before this field existed, or volumes never registered with the cloud.
CloudVolumeId string `json:"cloud_volume_id,omitempty"`
// DevicePath is the path to the loop device node
DevicePath string `json:"device_path"`
// MountPath is where the volume is mounted
MountPath string `json:"mount_path"`
// Mounted indicates if the volume is currently mounted
Mounted bool `json:"mounted"`
// ReadOnly indicates if the mount is read-only
ReadOnly bool `json:"read_only"`
// Mode is the disk I/O mode used for this mount (universal or accelerator)
Mode storage_v1alpha.DiskVolumeVolumeMode `json:"mode,omitempty"`
// LeaseNonce is the volume lease nonce from remote Disk API
LeaseNonce string `json:"lease_nonce,omitempty"`
}
MountState represents the state of a disk mount
type RegisterVolumeRequest ¶ added in v0.14.0
type RegisterVolumeRequest struct {
// LocalVolumeID is the node's identifier for the volume. It seeds the
// cloud volume's name and UUID, which is what makes registration
// idempotent across retries.
LocalVolumeID string
// ClusterID scopes the name, so two clusters in one organization that each
// hold a disk called "data" do not land on the same cloud volume and
// interleave their backups.
ClusterID string
// DisplayName is the operator-facing disk name, recorded as metadata.
DisplayName string
SizeBytes int64
Filesystem string
}
RegisterVolumeRequest describes a local volume to register.
type SnapshotRequest ¶ added in v0.14.0
type SnapshotRequest struct {
// VolumeID is the cloud volume the update belongs to.
VolumeID string
// ImagePath is the backing file to snapshot.
ImagePath string
// Name and Filesystem are recorded in the snapshot header so a restore
// knows what it is rebuilding.
Name string
Filesystem string
// SnapshotName optionally pins this as a named restore point.
SnapshotName string
// LeaseNonce is required when the volume has an active lease.
LeaseNonce string
// StagingDir is where the compressed snapshot is written before upload.
// Defaults to the image's own directory.
StagingDir string
}
SnapshotRequest describes one image to snapshot and upload.
type State ¶
type State struct {
Volumes map[string]*VolumeState `json:"volumes"`
Mounts map[string]*MountState `json:"mounts"`
// contains filtered or unexported fields
}
State represents the persisted state of disk volumes and mounts
func (*State) DeleteMount ¶
DeleteMount removes a mount state
func (*State) DeleteMountAndSave ¶
DeleteMountAndSave atomically removes a mount state and persists to disk.
func (*State) DeleteVolume ¶
DeleteVolume removes a volume state
func (*State) DeleteVolumeAndSave ¶
DeleteVolumeAndSave atomically removes a volume state and persists to disk.
func (*State) GetMount ¶
func (s *State) GetMount(entityId string) *MountState
GetMount returns a copy of a mount state by entity ID
func (*State) GetVolume ¶
func (s *State) GetVolume(entityId string) *VolumeState
GetVolume returns a copy of a volume state by entity ID
func (*State) GetVolumeByVolumeId ¶
func (s *State) GetVolumeByVolumeId(volumeId string) *VolumeState
GetVolumeByVolumeId returns a copy of a volume state by volume ID
func (*State) LeaseNonceForCloudVolume ¶ added in v0.14.0
LeaseNonceForCloudVolume returns the lease nonce held by a mount whose backing volume has the given cloud volume id, or "" if none is held.
The uploader is handed a volume's cloud id, but mount state keys off the local disk_volume entity id, so the two cannot be compared directly. This resolves cloud id -> volume entity id -> mount under a single read lock.
func (*State) ListMounts ¶
func (s *State) ListMounts() []*MountState
ListMounts returns copies of all mount states
func (*State) ListVolumes ¶
func (s *State) ListVolumes() []*VolumeState
ListVolumes returns copies of all volume states
func (*State) Save ¶
Save persists the state to disk atomically. Callers that need to mutate and save atomically should use the combined methods (SetVolumeAndSave, SetMountAndSave, etc.) instead.
func (*State) SetCloudVolumeId ¶ added in v0.14.0
SetCloudVolumeId records a volume's miren.cloud identifier and persists it. It mutates the stored volume in place under the lock rather than taking a whole VolumeState, so it cannot clobber mount fields another path set while the caller was talking to the cloud.
func (*State) SetMount ¶
func (s *State) SetMount(entityId string, mount *MountState)
SetMount sets a mount state
func (*State) SetMountAndSave ¶
func (s *State) SetMountAndSave(entityId string, mount *MountState) error
SetMountAndSave atomically sets a mount state and persists to disk.
func (*State) SetMountFromVolume ¶
func (s *State) SetMountFromVolume(volumeId string, mount *MountState) (devicePath, mountPath string, err error)
SetMountFromVolume atomically reads the current volume state and, if the volume is mounted, creates a mount entry using the volume's live device and mount paths. This avoids a TOCTOU race where the volume controller could update mount fields between a GetVolume call and a SetMount call. Returns the volume's DevicePath and MountPath on success, or an error if the volume is not found or not mounted.
func (*State) SetVolume ¶
func (s *State) SetVolume(entityId string, volume *VolumeState)
SetVolume sets a volume state
func (*State) SetVolumeAndSave ¶
func (s *State) SetVolumeAndSave(entityId string, volume *VolumeState) error
SetVolumeAndSave atomically sets a volume state and persists to disk.
type UpdateInfo ¶ added in v0.14.0
type UpdateInfo struct {
UpdateID string `json:"update_id"`
Kind string `json:"kind"`
OrderingKey string `json:"ordering_key"`
EndKey string `json:"end_key,omitempty"`
Size int64 `json:"size"`
SnapshotName string `json:"snapshot_name,omitempty"`
}
UpdateInfo describes one update the cloud is holding.
type UpdateKind ¶ added in v0.14.0
type UpdateKind string
UpdateKind names a producer format in the cloud's volume update stream.
Every kind shares the same transport and the same ordering model: each update carries an ordering key that sorts lexicographically against its siblings of the same kind. What differs is the shape of that key.
const ( // KindLBDLog is a log segment written by the lbd kernel module in // accelerator mode. Its ordering key is the TAI64N label from the segment // filename, disk.<label>.log. KindLBDLog UpdateKind = "lbd_log" // KindLoopImage is a compressed snapshot of a universal-mode volume's // backing image. Its ordering key is a zero-padded 16-hex snapshot // sequence. KindLoopImage UpdateKind = "loop_image" )
type UploadRequest ¶ added in v0.14.0
type UploadRequest struct {
Kind UpdateKind
OrderingKey string
// EndKey bounds range-valued kinds. Neither kind here uses it; the cloud
// rejects it for lbd_log and loop_image.
EndKey string
// SnapshotName names a restore point, pinning the update against cleanup.
// It must be unique per volume among live updates.
SnapshotName string
// Metadata is kind-specific payload detail. The cloud writes it to a
// sidecar object beside the payload rather than indexing it.
Metadata map[string]any
// LeaseNonce is required when the volume has an active lease.
LeaseNonce string
}
UploadRequest describes one update to be uploaded.
type VolumeState ¶
type VolumeState struct {
// EntityId is the ID of the disk_volume entity
EntityId string `json:"entity_id"`
// VolumeId is the local volume identifier. It names the mount point, so it
// is deliberately not the cloud's id: repointing it would relocate a live
// mount out from under whatever is using it.
VolumeId string `json:"volume_id"`
// CloudVolumeId is this volume's identifier in miren.cloud, empty until it
// has been registered there. Every cloud call keys off it, so empty means
// "not backed up yet" rather than "fall back to the local id", which the
// cloud would only reject.
CloudVolumeId string `json:"cloud_volume_id,omitempty"`
// Name is the human-readable name (from parent disk)
Name string `json:"name,omitempty"`
// DiskPath is the path to the volume data directory
DiskPath string `json:"disk_path"`
// SizeBytes is the volume size
SizeBytes int64 `json:"size_bytes"`
// Filesystem type (ext4, xfs, btrfs)
Filesystem string `json:"filesystem"`
// RemoteOnly indicates if this uses only remote storage
RemoteOnly bool `json:"remote_only"`
// Mode is the disk I/O mode (universal or accelerator)
Mode storage_v1alpha.DiskVolumeVolumeMode `json:"mode,omitempty"`
// DevicePath is the loop device backing this volume (alwaysMount modes only)
DevicePath string `json:"device_path,omitempty"`
// MountPath is where the volume is mounted (alwaysMount modes only)
MountPath string `json:"mount_path,omitempty"`
// Mounted indicates if the volume is currently mounted (alwaysMount modes only)
Mounted bool `json:"mounted,omitempty"`
}
VolumeState represents the state of a disk volume