cephfs

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 26 Imported by: 0

README

CephFS

Import github.com/JSYoo5B/ceph-testcontainers-go/cephfs to give an application that uses CephFS (libcephfs, go-ceph, the Python binding) a disposable cluster with the filesystem state its integration test needs: filesystems and their MDS topology, data pools, subvolume groups and subvolumes, snapshots and clones, principals restricted to one subvolume, directory pins, quiesce sets and client session limits. File I/O belongs to the client under test; the package never mounts CephFS on the test host. See API purpose and purpose tags.

go get github.com/JSYoo5B/ceph-testcontainers-go/cephfs

Order of use

  1. Start a cluster with filesystems: cephfs.Run(ctx, ceph.DefaultImage, opts...) creates the default filesystem tc-cephfs with one active MDS; cephfs.WithFilesystems(cephfs.Config{...}) selects others (also on ceph.Run, rbd.Run and rgw.Run), and cephfs.Start adds one to a running cluster. cephfs.Filesystems(cluster.Container) returns their handles.
  2. Prepare the state the scenario needs on a *cephfs.Filesystem: ScaleMDS, AddDataPool, CreateSubvolumeGroup / CreateSubvolume (quotas, data pools, RADOS namespaces), Subvolume.CreateSnapshot and SubvolumeSnapshot.Clone, Subvolume.Authorize (a principal for one subvolume), Subvolume.OverridePin, AddSnapshotSchedule, OverrideSessionTimeouts.
  3. Hand it to the SUT: run the client in a container attached with cluster.WithClient() (admin keyring) or grant.Client.WithIdentity() (one principal), and pass it fs.FilesystemName and the subvolume path.
  4. Reproduce conditions and observe: stop an MDS or fault.Pause a client, QuiesceSubvolumes, then check MDSStatus, WaitReady, Sessions, SubvolumeInfo, SubvolumeClone.Status, DataPools and the ceph observation APIs.
  5. Clean up: terminate the cluster; it removes owned filesystems, subvolumes, principals and daemons. Use the handles' Remove, Deauthorize and Restore only to test those steps or to restore state mid-test.
cluster, err := cephfs.Run(ctx, ceph.DefaultImage)
testcontainers.CleanupContainer(t, cluster)
if err != nil {
	t.Fatal(err)
}
fs := cephfs.Filesystems(cluster.Container)[0] // tc-cephfs
volume, err := fs.CreateSubvolume(ctx, cephfs.SubvolumeConfig{Name: "app", SizeBytes: 64 << 20})
if err != nil {
	t.Fatal(err)
}
client, err := testcontainers.Run(ctx, appImage, cluster.WithClient())
testcontainers.CleanupContainer(t, client)
if err != nil {
	t.Fatal(err)
}
// The client mounts fs.FilesystemName with libcephfs and works under volume.Path.

Concepts and limits

  • Everything in ceph applies to the cluster. Snapshot mirroring between two clusters is in cephfs/mirror.
  • Images by role: the Run image runs the MON, MGR and control CLI and needs the MGR volumes and mirroring modules; the client image (the Run image only for an aggregate) needs the Python cephfs binding, because pin reads, clone identity checks and scheduled snapshot listings run libcephfs in the client container; MDSs use ceph.ImageOptions.WithCephFSImage or the Run image; mirror daemons take their own image. ceph.DefaultImage (Tentacle 20.2.4) contains every role. Keep every role on the same release. Squid 19.2.5 is supported with no visible CephFS difference. See Releases and images.
  • Handles are owned by the cluster and bound to the native resource they created; a handle of another filesystem, or of a replaced resource, is refused. Fixture operations serialize within the caller's context; do not race them with raw ceph fs edits on the same resources.
  • Clients: no kernel or FUSE mount. Clients are userspace libraries in Linux containers, or the test process with host networking on a Linux Docker host. The fixture's own libcephfs probes appear briefly in Sessions.
  • MDS: names, keys, entrypoint and networking are fixed; each MDS has a 128 MiB cache. Damaged-metadata recovery, multi-rank replacement and MDS.AddReplacement with standbys are not provided.
  • Snapshots do not pause writers: use QuiesceSubvolumes or application synchronisation. Quota enforcement and usage accounting are native and can lag writes; removal moves data to Ceph's trash and purges asynchronously.
  • Native timing: a dead MDS is replaced only after mds_beacon_grace (15 s) unless failed with ceph mds fail; an unresponsive client is evicted after session_timeout (60 s) when another client wants its capabilities, otherwise after session_autoclose (300 s), and its address stays blocklisted for an hour; a mount against a silent MDS fails after client_mount_timeout (300 s). Shorten what a test waits for with OverrideSessionTimeouts and client options.

Reference

Documentation

Overview

Package cephfs prepares CephFS server fixtures in disposable Ceph clusters: filesystems and their MDS topology, subvolume groups, subvolumes, snapshots, clones, pins, quiesce sets and client authorization. Snapshot mirroring between two clusters is in the cephfs/mirror package.

Run starts a cluster with at least one filesystem. Start adds a filesystem to a cluster created by ceph.Run or another service package's Run, and WithFilesystems selects filesystems for any of those Run functions.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func WithFilesystems

func WithFilesystems(configs ...Config) ceph.Option

WithFilesystems creates named filesystems and their MDS topologies during Run. No arguments selects the default filesystem. Repeated options replace the list; Start can add further filesystems after Run returns.

Types

type CloneConfig

type CloneConfig struct {
	Name, GroupName, DataPool string
}

CloneConfig names a new clone in an existing group. DataPool optionally overrides the snapshot's data pool. Ceph copies the snapshot's quota and layout; with a DataPool override it clears the inherited RADOS namespace. Quota and namespace changes are deliberately not part of the clone request.

type Config

type Config struct {
	Name                string
	MetadataPool        ceph.PoolConfig
	DataPool            ceph.PoolConfig
	AdditionalDataPools []ceph.PoolConfig
	ActiveMDS           int
	// NoInitialMDS creates the filesystem/pools without a metadata daemon.
	// ActiveMDS and StandbyMDS must be omitted and StandbyReplay false.
	// The first ScaleMDS must request 1 active / 0 standby; later scale is ordinary.
	NoInitialMDS  bool
	StandbyMDS    int
	StandbyReplay bool
}

Config creates one named filesystem with dedicated pools and MDS daemons. Name defaults to tc-cephfs, ActiveMDS to one, and StandbyMDS to zero. Omitted pool names become <Name>-metadata and <Name>-data. Metadata and the default data pool must be replicated; additional pools may use erasure coding with AllowOverwrites. Each pool defaults to application=cephfs. Directory layouts select additional pools after filesystem creation. StandbyReplay assigns up to one journal follower per active rank; extra standbys stay idle.

Name is letters, digits, _, . or -, starting with a letter, digit or _. ActiveMDS (max_mds) is 1 to 256, and StandbyReplay needs StandbyMDS of at least one. Every pool gets application=cephfs and another application is refused; pools and OSD placements are validated before anything is created. The default data pool also stores inode backtraces and cannot be detached; additional pools are selected through subvolume, group or clone DataPool fields or directory layouts.

While a NoInitialMDS filesystem is cold its descriptor has a nil embedded container and an empty MDSs; do not call promoted container methods on it. WaitReady waits until its deadline, a fresh libcephfs mount fails after client_mount_timeout with errno 110 (ETIMEDOUT) and Ceph reports MDS_ALL_DOWN. ScaleMDS(ctx, 1, 0) starts the first MDS; after that the filesystem behaves like any other.

type Container

type Container struct {
	*ceph.Container
}

Container is a cluster started by Run. It embeds *ceph.Container, so every cluster method is available on it; pass its Container field to functions that take a *ceph.Container, such as those of this and the other service packages.

func Run

Run starts a disposable cluster for CephFS clients. It accepts every ceph.Run option and the options of other service packages. When no WithFilesystems option is given, it creates the default filesystem tc-cephfs with one active MDS. Bootstrap options that leave the cluster without OSDs or managers for the filesystem, such as ceph.ClusterConfig.WithNoInitialOSDs, are rejected; use ceph.Run for those stages. A non-nil Container returned with an error must still be terminated.

type DataPool

type DataPool struct {
	Name, FilesystemName string
	ID                   int64
	// contains filtered or unexported fields
}

DataPool identifies an additional pool attached by AddDataPool. Its private identity and state are shared by copied handles. Exported fields are descriptive; editing them does not redirect removal to another pool.

func (*DataPool) RemoveUnused added in v0.4.0

func (attachment *DataPool) RemoveUnused(ctx context.Context) error

RemoveUnused removes only the FSMap registration of a fresh helper attachment. A pool selected even once by a managed group/subvolume/clone is refused, including partial creations. Native groups/subvolumes must have no references and every RADOS namespace must be empty; unknown clone or retained snapshot information is conservatively refused. No pool, application tag or data is deleted. Native rm_data_pool cannot detect arbitrary POSIX layout references: the caller MUST stop external clients and reset all such layouts before removal, and prevent external edits from racing it. This method does not establish safety for a live workload. Default data pools are immutable. A copied handle shares removal state; retry reconciles a lost command reply.

type DataPoolState

type DataPoolState struct {
	Name    string
	ID      int64
	Default bool
}

DataPoolState reports a currently registered native filesystem data pool. ID distinguishes a pool recreated under the same name. Default marks the immutable first data pool, which also stores inode backtraces.

type Filesystem

type Filesystem struct {
	testcontainers.Container
	FilesystemName      string
	MetadataPool        string
	DataPool            string
	AdditionalDataPools []string
	// contains filtered or unexported fields
}

Filesystem describes one filesystem and embeds its first MDS container for compatibility with Start. MDSs exposes every owned metadata daemon. The cluster owns their lifetime. Clients use libcephfs through WithClient without a kernel or FUSE mount on the host.

FilesystemName is what clients pass as libcephfs filesystem_name. The embedded container is nil while a NoInitialMDS filesystem is cold and moves to a surviving daemon when the original is retired; use MDSs for the topology.

Operations on the filesystem and its handles wait for each other within the caller's context; a call canceled while waiting returns without changing Ceph and can be retried. The Ceph CLI has no compare-and-swap for these resources, so external ceph fs edits must not run on the same resources while a fixture operation is in progress. Termination removes the owned resources; explicit cleanup is for tests that assert removal or inspect intermediate state.

func Filesystems

func Filesystems(c *ceph.Container) []*Filesystem

Filesystems returns the cluster's owned filesystem descriptors sorted by filesystem name, including a descriptor whose setup partially failed. The cluster owns their MDS containers.

func Start

Start creates one filesystem with dedicated pools and its ActiveMDS+StandbyMDS daemons on an existing cluster. A zero config selects the default filesystem tc-cephfs with one active MDS named a. Every pool and OSD placement is validated before mutations. Existing filesystems are rejected instead of modified. Creating a second filesystem enables Ceph's global enable_multiple flag; the existing filesystem and its configuration are preserved.

Customizers apply to each MDS and must preserve its identity, config, keyring, entrypoint and networking. A non-nil result with an error identifies attempted resources; the cluster owns cleanup, including partial daemon startup.

func (*Filesystem) AddDataPool

func (fs *Filesystem) AddDataPool(ctx context.Context, name string) (*DataPool, error)

AddDataPool attaches an existing pool with application=cephfs and no prior filesystem role. Replicated pools and EC pools with allow_ec_overwrites are accepted. Metadata pools, cross-filesystem reuse and repeated attachments are refused. It creates or deletes no pools. A handle returned with an error records an attempted attachment; retrying the same name reconciles an unknown successful command using the original native IDs. External edits must not race these operations. Ceph's retained application tag after detachment must be inspected and explicitly cleared through Ceph before a new attachment.

Clear the retained tag with ceph osd pool application rm <name> cephfs data before attaching a detached pool again.

func (*Filesystem) AddSnapshotSchedule added in v0.4.0

func (fs *Filesystem) AddSnapshotSchedule(ctx context.Context, schedule SnapshotSchedule) (*SnapshotScheduleLease, error)

AddSnapshotSchedule adds a snapshot schedule, and its retention, to a directory of the filesystem through the MGR snap_schedule module, which takes "scheduled-…" snapshots in the directory's .snap. It never enables the module: enable it with override.SetMGRModule first, and wait until the active MGR, which restarts to load it, answers again. A disabled module is ceph.ErrInvalidRequest, and so is a directory that already has a schedule or another lease. The module keeps retention per directory, and a directory keeps retention rules after its last schedule is removed: rules that the new schedule inherits are refused with ceph.ErrInvalidRequest after the schedule was added, with a lease that removes it.

A non-nil lease returned with an error must be restored: after an add whose reply was lost, Restore takes the only schedule with the requested repeat and start as the lease's.

func (*Filesystem) CreateSubvolume

func (fs *Filesystem) CreateSubvolume(ctx context.Context, config SubvolumeConfig) (*Subvolume, error)

CreateSubvolume creates a fresh subvolume in the default or an existing named group. It rejects duplicates and unknown filesystem data pools before create. A non-nil result on failure identifies an attempted resource; it never removes partial data. Only successfully confirmed handles support Resize/Remove.

func (*Filesystem) CreateSubvolumeGroup

func (fs *Filesystem) CreateSubvolumeGroup(ctx context.Context, config SubvolumeGroupConfig) (*SubvolumeGroup, error)

CreateSubvolumeGroup creates a fresh group. Native Ceph's create is idempotent and can change an existing group's quota/layout; this helper rejects duplicates before issuing create. Do not race external subvolume/group commands with these operations. A non-nil handle on error records an attempted creation, but only a fully confirmed identity can be mutated. Cluster termination cleans up the entire disposable filesystem even after partial creation.

func (*Filesystem) DataPools

func (fs *Filesystem) DataPools(ctx context.Context) ([]DataPoolState, error)

DataPools reads the authoritative FSMap registration and current pool IDs. AdditionalDataPools in the creation descriptor describes initial settings; this method also reports subsequent native attachments and removals.

func (*Filesystem) MDSStatus

func (fs *Filesystem) MDSStatus(ctx context.Context) (*FilesystemStatus, error)

MDSStatus reads one native FSMap, so rank ownership and standby state come from the same epoch. Active ranks include external daemons with Owned=false; standby lists contain only this fixture's daemons with matching affinity.

func (*Filesystem) MDSs

func (fs *Filesystem) MDSs() []*MDS

MDSs returns a snapshot of this filesystem's owned daemons in creation order.

func (*Filesystem) OverrideSessionTimeouts added in v0.4.0

func (fs *Filesystem) OverrideSessionTimeouts(ctx context.Context, requested SessionTimeouts) (*SessionTimeoutsOverrideHandle, error)

OverrideSessionTimeouts sets both limits so a test can observe evicted clients in seconds instead of Ceph's default 60 and 300 seconds. Each value must be a whole number of seconds and at least 30 seconds, the native minimum. Only one handle per filesystem may be active. The native CLI changes one value per command, so apply and restore are not atomic.

func (*Filesystem) QuiesceSubvolumes

func (fs *Filesystem) QuiesceSubvolumes(ctx context.Context, volumes []*Subvolume, config QuiesceConfig) (*Quiesce, error)

QuiesceSubvolumes pauses I/O to confirmed owned subvolumes as one native set. It uses --if-version=0 to create exclusively, validates every current resource identity, and awaits QUIESCED with finite native timeout and expiration. Existing sets and application writers remain caller-owned. Take checkpoints with client/admin APIs while paused, then explicitly Release. Multiple native sets can overlap paths; releasing this set does not cancel other sets.

func (*Filesystem) Remove added in v0.4.0

func (fs *Filesystem) Remove(ctx context.Context) error

Remove deletes this owned filesystem: it gracefully stops its ranks and removes it in the FSMap, terminates its MDS daemons, deletes their Cephx keys and removes the metadata, default data and AdditionalDataPools that its configuration created, together with their CRUSH rules and EC profiles. Pools attached later with AddDataPool are detached but kept; remove them with ceph.Pool.Remove (see ceph.Container.Pool). File data in the removed pools is destroyed. Stop clients, CephFS mirrors and subvolume operations on the filesystem first; their handles fail afterwards. A retry after an error continues with whatever remains. If graceful shutdown cannot complete within the caller or startup timeout, removal returns an error without forcing the MDSs to fail. The filesystem may remain marked down and stays owned for a later retry.

Remove acts on this descriptor. One that Remove already removed, or that is not the one the cluster owns for its name, returns an error.

It requests fs set <name> down true and requires the filesystem's native up map to be empty before fs rm, so a rank that is still stopping or reconnecting blocks removal, and health warnings never authorize a forced fs fail.

func (*Filesystem) ScaleMDS

func (fs *Filesystem) ScaleMDS(ctx context.Context, active, standby int) (returnErr error)

ScaleMDS changes the active/standby daemon counts of this existing filesystem without recreating its pools or data. Active must be 1..256 and Standby must be non-negative. Additional MDSs preserve the initial customizers and affinity. Ceph hands retired ranks back to standbys before this method stops surplus owned daemons. Ordinary standbys are removed before replay followers.

The explicit topology request acknowledges Ceph's max_mds health-warning confirmation (--yes-i-really-mean-it) in this disposable fixture. Run scaling with healthy owned daemons and without concurrent external failure injection or FSMap edits. An error retains desired counts and every partial resource for cluster cleanup; it never deletes the filesystem, its pools or file data. Scaling to zero standby leaves the filesystem's replay preference unchanged.

func (*Filesystem) SessionTimeouts

func (fs *Filesystem) SessionTimeouts(ctx context.Context) (SessionTimeouts, error)

SessionTimeouts reads both limits from the filesystem's current MDSMap.

func (*Filesystem) Sessions

func (fs *Filesystem) Sessions(ctx context.Context) ([]Session, error)

Sessions lists client sessions from every active rank of the filesystem, including the fixture's own short-lived libcephfs probes. Filter by Hostname or EntityID to find a particular client. It reads native state only.

func (*Filesystem) SubvolumeAuthorizedClients

func (fs *Filesystem) SubvolumeAuthorizedClients(ctx context.Context, name, group string) ([]SubvolumeAuthorizedClient, error)

SubvolumeAuthorizedClients reads native volumes authorization metadata, including principals created through raw Ceph. It grants no mutation ownership.

func (*Filesystem) SubvolumeGroupInfo

func (fs *Filesystem) SubvolumeGroupInfo(ctx context.Context, name string) (*SubvolumeGroupInfo, error)

SubvolumeGroupInfo queries the current native group quota/layout and path.

func (*Filesystem) SubvolumeGroups

func (fs *Filesystem) SubvolumeGroups(ctx context.Context) ([]string, error)

SubvolumeGroups lists native named groups, sorted by name. It omits Ceph's internal default group and includes groups created outside these helpers.

func (*Filesystem) SubvolumeInfo

func (fs *Filesystem) SubvolumeInfo(ctx context.Context, name, groupName string) (*SubvolumeInfo, error)

SubvolumeInfo queries current metadata. name identifies the subvolume and an empty groupName selects the default group. A snapshot-retained entry lacks a usable Path and is never accepted as an active owned resource.

func (*Filesystem) SubvolumeSnapshotInfo

func (fs *Filesystem) SubvolumeSnapshotInfo(ctx context.Context, subvolumeName, groupName, snapshotName string) (*SubvolumeSnapshotInfo, error)

SubvolumeSnapshotInfo queries native metadata for any existing snapshot. Reading an external snapshot does not grant mutation ownership.

func (*Filesystem) Subvolumes

func (fs *Filesystem) Subvolumes(ctx context.Context, groupName string) ([]string, error)

Subvolumes lists native names in groupName, sorted by name. Empty selects the default group. Native snapshot-retained entries can appear in this listing.

func (*Filesystem) WaitReady

func (fs *Filesystem) WaitReady(ctx context.Context) error

WaitReady waits for all configured ranks to be owned and active and all configured standbys to register. Replay mode also waits for journal followers. After a standby takes over a failed active daemon, use MDSStatus to check recovered ranks or restart a daemon before WaitReady; readiness includes the requested standby capacity.

Example (Select)
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/JSYoo5B/ceph-testcontainers-go/cephfs"
)

func main() {
	// This unavailable descriptor verifies expected API-error delivery and the
	// one-shot channel lifecycle without Docker. It is not a ready fixture or a
	// replacement for Run/Start; real callers use their owned filesystem.
	fs := &cephfs.Filesystem{}
	waitCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	resultCh := make(chan error, 1)
	var results <-chan error = resultCh // One result for one consumer, not a broadcast.
	joined := make(chan struct{})
	defer func() { cancel(); <-joined }() // Register before launching the worker.
	go func() {
		defer close(joined)
		resultCh <- fs.WaitReady(waitCtx)
		close(resultCh)
	}()

	var outcomeErr error
	var open bool
	select {
	case outcomeErr, open = <-results:
	case <-waitCtx.Done():
		cancel()
		<-joined
		outcomeErr, open = <-results
	}
	cancel()
	<-joined // Join before callbacks or fixture cleanup with a fresh context.
	if !open {
		panic("wait closed without a terminal result")
	}
	if _, open := <-results; open {
		panic("wait sent more than one terminal result")
	}
	consume := func(err error) {
		fmt.Println("consumer received error:", err != nil)
	}
	consume(outcomeErr) // Caller code after join, outside the wait's fixture gates.
	fmt.Println("worker joined and channel closed")
}
Output:
consumer received error: true
worker joined and channel closed

type FilesystemStatus

type FilesystemStatus struct {
	FilesystemName string
	FilesystemID   int64
	MaxMDS         int
	Active         []MDSStatus
	Standby        []MDSStatus
	StandbyReplay  []MDSStatus
}

FilesystemStatus contains active ranks and this fixture's ordinary/replay standbys. Standbys belonging to another filesystem are never counted.

type MDS

type MDS struct {
	testcontainers.Container
	ID             string
	FilesystemName string
	// contains filtered or unexported fields
}

MDS is an owned metadata daemon. ID is its static Ceph daemon name; MDSStatus reports its current rank and GID. Stop/Start can inject failures. Cluster termination removes stopped and partially initialized daemons too.

On a ceph.AddressDualStack cluster every MDS advertises a concrete IPv4 and IPv6 address, IPv4 first; ms_bind_prefer_ipv4 = false in its [mds.<ID>] section of a ceph.WithConfigFile file makes clients use IPv6.

func (*MDS) AddReplacement added in v0.4.0

func (stopped *MDS) AddReplacement(ctx context.Context) (*MDS, error)

AddReplacement starts a new indexed MDS for the filesystem of this stopped MDS, its sole original member, preserving its pools, data and desired one-active/zero-standby policy. The old name must already be globally absent and rank zero failed; native failure is caller-controlled. No native fail, auth deletion or old CID removal is performed. Once the new rank is ready, MDS.RemoveStopped can retire the original old container using the new healthy survivor.

Any failure after the auth/start attempt leaves this request cleanup-only, including its use as typed scaling/retirement authority. A nonnil result remains owned even on error. Retrying the original or an exact copied handle never implicitly starts another daemon or completes a partial request. A completed retry reattests and returns only the exact new handle. Direct Start/Stop, native policy/failure edits and exported-field edits must not run concurrently. Native name/GID and original Docker CID are independent evidence; this method does not establish process-to-GID attribution.

Without a standby, Ceph can keep a dead daemon registered as laggy; fail its GID explicitly with ceph mds fail <gid> before calling it. Do not start, stop or fail daemons by hand while it runs.

func (*MDS) RemoveStopped added in v0.4.0

func (daemon *MDS) RemoveStopped(ctx context.Context) error

RemoveStopped retires this original owned, stopped MDS container after its immutable daemon name has left every native filesystem and global standby list. Healthy original owned daemons must still serve every desired active rank. It neither fails a native MDS nor deletes its auth entity or changes desired capacity. Use Filesystem.ScaleMDS afterward to create missing replacement members.

Only successful original startups are eligible. A partial startup remains owned for cluster Terminate. An uncertain Docker removal retains the original handle for explicit retry; initial arbitrary absence is not success. Direct failure injection, Start/Stop and raw policy changes must not run concurrently.

type MDSStatus

type MDSStatus struct {
	Name  string `json:"name"`
	Rank  int    `json:"rank"`
	GID   uint64 `json:"gid"`
	State string `json:"state"`
	Owned bool   `json:"owned"`
}

MDSStatus records a metadata daemon's current native FSMap identity. GID changes after process restart. Ordinary standbys have rank -1; replay standbys follow the rank they would replace. Owned identifies this fixture's daemons.

type PinOverrideHandle added in v0.4.0

type PinOverrideHandle struct {
	// contains filtered or unexported fields
}

PinOverrideHandle manages restoration of one confirmed owned resource's policy field, retaining prior state and possibly uncertain application. Copies share restoration state. Retain a non-nil result even on error: cancellation or a lost reply can leave native state changed. Explicit Restore returns that field to its prior canonical virtual value; other fields, directories and data are preserved. It refuses a different current field or native resource identity. Same-value outside edits and changes below native text precision cannot be distinguished; do not race external pin edits or delete/recreate the directory while the handle is used.

func (*PinOverrideHandle) Restore added in v0.4.0

func (change *PinOverrideHandle) Restore(ctx context.Context) error

Restore confirms the same owned directory/inode and returns only this field to its previous canonical native value. It is idempotent across handle copies; after an uncertain reply, retry with a fresh context to reconcile readback.

type PinPolicy

type PinPolicy struct {
	Path              string
	Inode             uint64
	ExportRank        int
	Distributed       bool
	RandomProbability float64
}

PinPolicy reports the local virtual xattrs on the directory targeted by the native volumes pin command. For subvolumes, Path is the base directory, one level above the UUID data directory returned by SubvolumeInfo. ExportRank -1, Distributed false and RandomProbability 0 are native virtual defaults. These local values do not report inherited policy or actual MDS authority. RandomProbability has the precision of native virtual-xattr text.

type PinSetting

type PinSetting struct {
	Type  PinType
	Value float64
}

PinSetting changes one policy field. Export accepts an integer owned active rank, or -1 to remove the local pin. Distributed accepts 0 or 1. Random accepts a probability in [0,1], additionally capped by the MDS's mds_export_ephemeral_random_max. Ephemeral feature configuration is caller- controlled; setting a policy does not prove its runtime effect.

type PinType

type PinType string

PinType selects one native directory policy. Policies can coexist; ancestry and Ceph's native precedence determine actual subtree placement.

const (
	// PinExport pins the directory to one active rank held by an owned MDS;
	// the value -1 removes the local pin.
	PinExport PinType = "export"
	// PinDistributed spreads the immediate children across ranks; the value
	// is 0 or 1.
	PinDistributed PinType = "distributed"
	// PinRandom pins descendants to a random rank with a probability in
	// [0, 1], further capped by mds_export_ephemeral_random_max.
	PinRandom PinType = "random"
)

type Quiesce

type Quiesce struct {
	// contains filtered or unexported fields
}

Quiesce owns a newly created, unique native quiesce set. Copies share state. Release confirms the captured QUIESCED version, so an outside edit or expiration cannot masquerade as a consistent checkpoint. An uncertain create may return a non-nil handle plus an error; retain it or let its native timer expire before terminating the cluster. Never externally edit this set ID.

func (*Quiesce) ID

func (q *Quiesce) ID() string

ID returns the native quiesce set ID, for example to inspect it with ceph fs quiesce <fs> --set-id <id> --query.

func (*Quiesce) Release

func (q *Quiesce) Release(ctx context.Context) error

Release resumes this set's I/O only at its captured QUIESCED version, using native optimistic concurrency. Expired/timed-out/canceled sets are reported as errors, so a test cannot treat an interrupted checkpoint as consistent. Lost replies can be retried; confirmed RELEASED copies become no-ops. Native set records are retained by the QDB and disposed of with the cluster.

func (*Quiesce) Status

func (q *Quiesce) Status(ctx context.Context) (*QuiesceState, error)

Status queries this set without renewing the native expiration timer. It verifies filesystem and exact nonexcluded members; it does not adopt new versions as permission to release an externally edited set.

type QuiesceConfig

type QuiesceConfig struct {
	Timeout, Expiration time.Duration
}

QuiesceConfig bounds reaching the I/O pause and its lifetime. Both durations must be at least one second. Expiration is a native safety timer; observing Status does not extend it. This fixture does not pause processes.

type QuiesceState

type QuiesceState struct {
	ID                  string
	Version             uint64
	State               string
	Timeout, Expiration float64
	Members             []string
}

QuiesceState describes one native set. Version changes on native state transitions or edits. Members are native file: paths, not mutable handle fields.

type Session

type Session struct {
	Rank     int
	ID       uint64
	Address  string
	State    string
	EntityID string
	Hostname string
	Root     string
	PID      string
	Caps     int
}

Session is one client session reported by an active MDS rank. A client with sessions on several ranks appears once per rank. Address is the session's IP:port/nonce, the same form BlocklistEntries reports, so an evicted session can be matched to its blocklist entry. EntityID, Hostname, Root and PID come from the metadata the client sent when it opened the session.

type SessionTimeouts

type SessionTimeouts struct {
	Timeout, Autoclose time.Duration
}

SessionTimeouts are the filesystem's MDSMap client session limits. A silent client whose capabilities nobody wants stays open until Autoclose. Once another client asks for its capabilities, the MDS evicts it as soon as Timeout passes. With Ceph's default mds_session_blocklist_on_timeout the evicted address is blocklisted. These are filesystem settings, not central configuration, so override.SetConfig cannot change them. Native values are whole seconds.

type SessionTimeoutsOverrideHandle added in v0.4.0

type SessionTimeoutsOverrideHandle struct {
	// contains filtered or unexported fields
}

SessionTimeoutsOverrideHandle manages restoration of both session limits, retaining prior state and ownership even when application is uncertain. Copies share restoration state. Retain a non-nil result even on error: a lost reply can leave either value changed.

func (*SessionTimeoutsOverrideHandle) Restore added in v0.4.0

func (change *SessionTimeoutsOverrideHandle) Restore(ctx context.Context) error

Restore returns both limits to the values captured before the change. It is idempotent across handle copies. A value that is neither the applied nor the captured one is an outside edit and is refused rather than overwritten.

type SnapshotPendingClone

type SnapshotPendingClone struct {
	Name      string `json:"name"`
	GroupName string `json:"target_group"`
}

SnapshotPendingClone identifies a native clone still using a snapshot. An empty GroupName selects the default group.

type SnapshotSchedule added in v0.4.0

type SnapshotSchedule struct {
	// Path is the directory to snapshot, an absolute path in the filesystem,
	// such as "/" or "/data". It must exist.
	Path string
	// Repeat is how often a snapshot is taken: a positive number and one of
	// m (minutes), h, d, w, M (months) or y, such as "6h" or "1m". The module
	// takes minutes only while mgr/snap_schedule/allow_m_granularity is true,
	// which override.SetConfig can set for a test.
	Repeat string
	// Start is the schedule's first time slot; the zero time leaves the
	// module's default, midnight of the day the schedule is added, in UTC.
	Start time.Time
	// Retention keeps this many of the schedule's snapshots per period, keyed
	// by m, h, d, w, M or y, or n for the newest snapshots of any period. Nil
	// keeps every snapshot that the module takes.
	Retention map[string]int
}

SnapshotSchedule configures AddSnapshotSchedule.

type SnapshotScheduleLease added in v0.4.0

type SnapshotScheduleLease struct {
	// Path, Repeat, Start and Retention are the requested schedule.
	Path, Repeat string
	Start        time.Time
	Retention    map[string]int
	// contains filtered or unexported fields
}

SnapshotScheduleLease owns one snapshot schedule of a directory and the retention rules that it added. Restore removes them; the snapshots stay. Retain a non-nil lease returned with an error: the schedule may have been added.

func (*SnapshotScheduleLease) Restore added in v0.4.0

func (l *SnapshotScheduleLease) Restore(ctx context.Context) error

Restore removes the retention rules that the lease added, then its schedule; the snapshots stay. The module keeps retention per directory: every schedule of the directory shares it, and it stays after the last schedule is removed. Restore reads the directory back on every call, so a retry continues where an earlier call stopped, and it completes only once both the lease's rules and its schedule are confirmed gone:

  • a rule that the directory no longer lists, or that the module reports as not set when no schedule shows the retention, is done;
  • while another schedule of the directory, of any repeat, would lose a rule of the lease, Restore refuses with ceph.ErrInvalidRequest without a change, and so it does for a rule whose count changed or a schedule with the lease's repeat that is not the lease's. The lease stays retryable, for example after the other schedule's owner removed it.

func (*SnapshotScheduleLease) Snapshots added in v0.4.0

func (l *SnapshotScheduleLease) Snapshots(ctx context.Context) ([]string, error)

Snapshots lists the snapshots in the directory's .snap that the module took, named "scheduled-…", oldest first, through libcephfs in the client container.

func (*SnapshotScheduleLease) Status added in v0.4.0

Status reads the schedule's state from the snap_schedule module.

type SnapshotScheduleStatus added in v0.4.0

type SnapshotScheduleStatus struct {
	// Path and Schedule identify the schedule; Active is false after the
	// module deactivated it.
	Path, Schedule string
	Active         bool
	// Start is the schedule's first time slot and Added the time the module
	// added it, both in UTC; with Path and Schedule they identify one
	// schedule, since a directory can have several with the same repeat.
	Start, Added time.Time
	// Retention is the module's retention specification. The module keeps it
	// per directory: every schedule of the directory shares it, and it stays
	// after the directory's last schedule is removed.
	Retention map[string]int
	// Created and Pruned count the snapshots that the module took and
	// removed; First and Last are its first and last snapshot times, zero
	// before the first.
	Created, Pruned int
	First, Last     time.Time
	// Raw is the module's JSON for the schedule.
	Raw json.RawMessage
	// contains filtered or unexported fields
}

SnapshotScheduleStatus is what the snap_schedule module reports for a schedule: native state, not the requested SnapshotSchedule.

type Subvolume

type Subvolume struct {
	Name           string
	GroupName      string
	FilesystemName string
	Path           string
	// contains filtered or unexported fields
}

Subvolume is an owned subvolume returned by CreateSubvolume. Its public fields describe creation. SubvolumeInfo queries current native state. Remove deletes this directory tree and its contents, preserving its filesystem and pools; native trash purging is asynchronous.

func (*Subvolume) Authorize added in v0.4.0

Authorize creates a fresh identity with an explicit fresh key, then asks MGR volumes to grant its exact native UUID path and pool/namespace. It refuses existing principals and non-isolated layouts. Native --allow_existing_id is used only for this immediately created, key-verified identity, never to adopt a user. MON visibility is restricted to this filesystem. This grant provides no layout, snapshot or root-squash administration capabilities.

A non-nil result with an error may contain an owned partial creation. It is never silently adopted by a second Authorize call; inspect through Ceph or explicitly SubvolumeAuthorization.Deauthorize when its Client creation was confirmed. External auth/layout edits must not race these operations.

func (*Subvolume) CreateSnapshot added in v0.4.0

func (subvolume *Subvolume) CreateSnapshot(ctx context.Context, name string) (*SubvolumeSnapshot, error)

CreateSnapshot creates a fresh snapshot without modifying an existing same-named snapshot. Application writers must be synchronized by the caller before taking a consistency-sensitive checkpoint. External CLI mutations must not race the native preflight and creation.

func (*Subvolume) OverridePin added in v0.4.0

func (volume *Subvolume) OverridePin(ctx context.Context, setting PinSetting) (*PinOverrideHandle, error)

OverridePin changes one local field using Ceph's volumes command. The native subvolume data path is left intact. Overlapping handles for the same target/field are rejected; independent fields may be changed separately.

func (*Subvolume) PinPolicy added in v0.4.0

func (volume *Subvolume) PinPolicy(ctx context.Context) (*PinPolicy, error)

PinPolicy reads all three local fields on an owned subvolume's base directory through libcephfs inside the client container (ClientContainer). No host mount or Go native dependency is required; the client image must supply Python libcephfs.

func (*Subvolume) Remove added in v0.4.0

func (subvolume *Subvolume) Remove(ctx context.Context) error

Remove removes this owned directory tree and its contents without --force or --retain-snapshots. Native Ceph refuses subvolumes with snapshots; use the snapshot helpers to remove owned snapshots first. Trash purging is async. Repeat removal after confirmed success is a no-op; external edits must not race this operation. Its filesystem, groups and pools remain available.

func (*Subvolume) Resize added in v0.4.0

func (subvolume *Subvolume) Resize(ctx context.Context, sizeBytes int64) error

Resize changes only an owned subvolume's quota, with the same zero and --no_shrink behavior as SubvolumeGroup.Resize.

func (*Subvolume) Snapshots added in v0.4.0

func (subvolume *Subvolume) Snapshots(ctx context.Context) ([]string, error)

Snapshots lists native snapshots of an owned subvolume, including snapshots made by an external client. Only snapshots returned by this fixture's Subvolume.CreateSnapshot can be removed or cloned through an owned descriptor.

type SubvolumeAuthorization

type SubvolumeAuthorization struct {
	Client         *ceph.ClientConfig
	AuthID         string
	Access         string
	FilesystemName string
	SubvolumeName  string
	GroupName      string
	Path           string
	DataPool       string
	PoolNamespace  string
	// contains filtered or unexported fields
}

SubvolumeAuthorization describes an owned native volumes grant. Client provides credentials for ClientConfig.WithIdentity and independent Linux clients. Exported fields are descriptions; changing them cannot redirect mutations. Copies share grant/deauthorization state. The namespace cap covers the entire actual namespace, which may be shared by clones inheriting a source layout.

func (*SubvolumeAuthorization) Deauthorize added in v0.4.0

func (grant *SubvolumeAuthorization) Deauthorize(ctx context.Context) error

Deauthorize removes only this native path/pool/namespace grant and volumes metadata. It verifies the original volume, layout and principal key; unrelated capabilities and the key are preserved unless native Ceph deletes an identity with no remaining rights. It does not revoke overlapping grants added separately, remove files or evict established sessions. Use a fresh client to observe changed permissions, then SubvolumeAuthorization.EvictClients when needed. A lost reply keeps retry state; native metadata/caps are reconciled before repeating the command. Outside edits after an uncertain result are surfaced without restoring or overwriting them.

func (*SubvolumeAuthorization) EvictClients added in v0.4.0

func (grant *SubvolumeAuthorization) EvictClients(ctx context.Context) error

EvictClients evicts existing sessions with this principal and the exact original subvolume mount root. Deauthorization must have completed first; independently mounted roots and future connections permitted by other grants are outside this native operation's scope. Eviction may blocklist the client's connection address. A native error may represent partial eviction across MDS ranks; a retry repeats the same owned scope.

To remove the principal itself afterwards, call grant.Client.Delete.

type SubvolumeAuthorizationConfig

type SubvolumeAuthorizationConfig struct {
	ClientID string
	Access   string
}

SubvolumeAuthorizationConfig creates a fresh Cephx principal. Access must be "r" or "rw". Namespace-isolated subvolumes are required: a path cap alone cannot restrict direct RADOS access to the subvolume's file data.

type SubvolumeAuthorizedClient

type SubvolumeAuthorizedClient struct {
	AuthID string
	Access string
}

SubvolumeAuthorizedClient is one entry in native authorized_list. This is volumes metadata, not a complete audit of independently edited Cephx caps.

type SubvolumeClone

type SubvolumeClone struct {
	Name, GroupName, FilesystemName string
	// contains filtered or unexported fields
}

SubvolumeClone is an asynchronous, owned clone request. SubvolumeClone.Wait returns a usable subvolume only after native cloning completes. A non-nil descriptor on error records the attempted request but cannot be adopted or canceled automatically. Cluster cleanup removes incomplete data too.

func (*SubvolumeClone) Cancel added in v0.4.0

func (clone *SubvolumeClone) Cancel(ctx context.Context) error

Cancel requests native cancellation of an owned pending or in-progress clone, then waits for canceled state and release of this clone's source snapshot protection. Its partial target is retained. A completed or failed clone is never treated as successfully canceled. Copied handles share identity; a retry after a lost reply first reconciles native canceled state. The original source snapshot must still exist. Native external clone/source edits must not race this operation; pending UUIDs are read from version-checked native volumes metadata captured immediately after submission.

func (*SubvolumeClone) RemovePartial added in v0.4.0

func (clone *SubvolumeClone) RemovePartial(ctx context.Context) error

RemovePartial explicitly removes an owned failed or canceled target with native --force. It refuses pending/in-progress/completed clones, replaced target incarnations and unresolved source protection. The original snapshot must remain present and unchanged. No source data or snapshots are removed. Native removal moves the target into asynchronous trash; success confirms logical absence, not physical purge completion. A failed command retains shared retry state so an unknown successful removal can be reconciled without deleting a subsequently recreated same-named target.

func (*SubvolumeClone) Status added in v0.4.0

func (clone *SubvolumeClone) Status(ctx context.Context) (*SubvolumeCloneStatus, error)

Status inspects this owned request. Native status is read-only; failed and canceled targets are preserved. Every query verifies the captured native UUID, inode and birth time too.

func (*SubvolumeClone) Wait added in v0.4.0

func (clone *SubvolumeClone) Wait(ctx context.Context) (*Subvolume, error)

Wait waits within the cluster startup timeout or the caller's earlier deadline. A timeout leaves cloning running and can be retried. Native failed/canceled states return promptly without removing partial data. A successful result supports existing Subvolume.Resize/Subvolume.Remove methods.

type SubvolumeCloneStatus

type SubvolumeCloneStatus struct {
	State, SourceFilesystem, SourceSubvolume, SourceGroup, SourceSnapshot string
	FailureErrno                                                          int
	FailureMessage                                                        string
	Progress                                                              map[string]string
}

SubvolumeCloneStatus reports native pending, in-progress, complete, failed or canceled state. FailureErrno is zero when no native failure was recorded. Source fields are normally absent after successful completion.

type SubvolumeConfig

type SubvolumeConfig struct {
	Name              string
	GroupName         string
	SizeBytes         int64
	DataPool          string
	NamespaceIsolated bool
}

SubvolumeConfig creates a directory tree managed by the MGR volumes module. An empty GroupName selects Ceph's default group. Zero SizeBytes leaves it unlimited. DataPool selects an existing filesystem data pool; empty inherits the group's layout. NamespaceIsolated gives file data a separate RADOS namespace; client access still requires appropriate Cephx capabilities.

type SubvolumeGroup

type SubvolumeGroup struct {
	Name           string
	FilesystemName string
	Path           string
	// contains filtered or unexported fields
}

SubvolumeGroup is an owned group returned by CreateSubvolumeGroup. Public fields are creation-time descriptions; mutations use the private identity captured after successful creation. Get current quota through SubvolumeGroupInfo. Removing a group requires it to be empty.

func (*SubvolumeGroup) OverridePin added in v0.4.0

func (group *SubvolumeGroup) OverridePin(ctx context.Context, setting PinSetting) (*PinOverrideHandle, error)

OverridePin changes one owned group's local policy field.

func (*SubvolumeGroup) PinPolicy added in v0.4.0

func (group *SubvolumeGroup) PinPolicy(ctx context.Context) (*PinPolicy, error)

PinPolicy reads an owned group's local directory policies.

func (*SubvolumeGroup) Remove added in v0.4.0

func (group *SubvolumeGroup) Remove(ctx context.Context) error

Remove removes an owned empty group without --force. A native refusal (for example a nonempty group) preserves its handle for retry. A repeat call after confirmed success is a no-op. External edits must not race removal.

func (*SubvolumeGroup) Resize added in v0.4.0

func (group *SubvolumeGroup) Resize(ctx context.Context, sizeBytes int64) error

Resize changes only an owned group's quota. Zero removes its limit. --no_shrink refuses a positive limit below native current usage; it never truncates files. Directory accounting and quota enforcement are native CephFS behavior and can lag concurrent writes.

type SubvolumeGroupConfig

type SubvolumeGroupConfig struct {
	Name      string
	SizeBytes int64
	DataPool  string
}

SubvolumeGroupConfig creates a named group inside an existing filesystem. SizeBytes is its aggregate directory quota; zero leaves it unlimited. DataPool optionally selects one of the filesystem's existing data pools. These helpers do not create pools, filesystems, MDS daemons or orchestrator services.

type SubvolumeGroupInfo

type SubvolumeGroupInfo struct {
	Name       string
	Path       string
	DataPool   string
	QuotaBytes int64
	BytesUsed  int64
	CreatedAt  string
}

SubvolumeGroupInfo reports native group metadata. QuotaBytes is zero for an unlimited quota. BytesUsed is Ceph's directory size accounting, which can lag recent writes. CreatedAt is the directory birth time used by the native volumes module.

type SubvolumeInfo

type SubvolumeInfo struct {
	Name          string
	GroupName     string
	Path          string
	DataPool      string
	PoolNamespace string
	QuotaBytes    int64
	BytesUsed     int64
	CreatedAt     string
	State         string
	Type          string
}

SubvolumeInfo reports a native subvolume, including its real mount path and RADOS namespace. Read-only queries also describe resources created outside these helpers, but those resources cannot be resized or removed through an owned handle. QuotaBytes is zero for unlimited.

type SubvolumeSnapshot

type SubvolumeSnapshot struct {
	Name, SubvolumeName, GroupName, FilesystemName, Path string
	// contains filtered or unexported fields
}

SubvolumeSnapshot is an owned snapshot of a confirmed subvolume. Its public fields describe creation; mutations use the captured private identity. Snapshot creation does not quiesce concurrent application writers.

func (*SubvolumeSnapshot) Clone added in v0.4.0

func (snapshot *SubvolumeSnapshot) Clone(ctx context.Context, config CloneConfig) (*SubvolumeClone, error)

Clone submits an asynchronous copy to a fresh subvolume. Duplicate targets are rejected; the source snapshot is retained. Immediately after submission it captures the target UUID, inode and birth time from version-checked native volumes metadata inside the client container. External edits must not race submission. A failed command or identity read returns a non-nil descriptor for inspection, but cannot be adopted or mutated through this API. Failed/canceled targets are retained until explicit SubvolumeClone.RemovePartial or raw Ceph cleanup.

func (*SubvolumeSnapshot) Remove added in v0.4.0

func (snapshot *SubvolumeSnapshot) Remove(ctx context.Context) error

Remove removes only this owned snapshot without --force. Pending clones protect their source snapshot both in this preflight and in native Ceph. Copies share removal state, and retry reconciles an uncertain successful deletion. Source data and completed clones are preserved.

type SubvolumeSnapshotInfo

type SubvolumeSnapshotInfo struct {
	Name, SubvolumeName, GroupName, Path, CreatedAt, DataPool string
	HasPendingClones                                          bool
	PendingClones                                             []SnapshotPendingClone
	OrphanClonesCount                                         int
}

SubvolumeSnapshotInfo contains current native snapshot metadata. Path identifies the frozen data directory, including Ceph's incarnation UUID.

Directories

Path Synopsis
Package mirror mirrors CephFS snapshots of selected directories from a filesystem in one Ceph cluster to a filesystem in another, with native cephfs-mirror daemons: directory enrollment, peer management, MGR reassignment, process quiescence and typed readiness observation.
Package mirror mirrors CephFS snapshots of selected directories from a filesystem in one Ceph cluster to a filesystem in another, with native cephfs-mirror daemons: directory enrollment, peer management, MGR reassignment, process quiescence and typed readiness observation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL