provision

package
v0.31.2 Latest Latest
Warning

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

Go to latest
Published: Oct 26, 2026 License: BSD-3-Clause Imports: 39 Imported by: 0

Documentation

Overview

Package provision is `fileshare provisioner`: the privileged half of fileshare, which creates the storage a volume share is served from -- a ZFS dataset, a btrfs subvolume, an XFS or ext4 directory under a project quota -- and nothing else. See docs/volumes.md for the design, and proto/fileshare/provision/v1/provision.proto for the protocol.

fileshare itself parses five network protocols for strangers and holds no privilege. Creating storage needs CAP_SYS_ADMIN (quotactl, the btrfs quota ioctls, /dev/zfs, mount(2)), so that part is this separate process, behind a unix socket, answering one uid, with a closed set of verbs and requests that never carry a path.

It builds on Linux and macOS -- the second only so that its tests run on a developer's Mac with fake backends; the command refuses to start anywhere but Linux. Elsewhere the package is empty.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ParseSize

func ParseSize(s string) (uint64, error)

ParseSize reads a size in bytes: a number, optionally followed by K, M, G, T, P or E -- powers of 1024, as zfs(8) and df(1) mean them -- with an optional "B" or "iB" after the letter.

func Run

func Run(ctx context.Context, cfg *Config, out io.Writer) error

Run is `fileshare provisioner`: it checks every parent on disk, mounts again what a reboot unmounted, and serves until ctx is done.

Types

type Config

type Config struct {
	// Listen is unix://<absolute path>, and nothing else: CSI's rule, "Only
	// UNIX Domain Sockets MAY be used as endpoints". The socket is made 0660,
	// owned by this process and the group below.
	Listen string `hcl:"listen"`
	// ClientUID is the one uid answered: fileshare's.
	//
	// ⛔ Not 0. fileshare must not run as root, nor with CAP_SYS_RESOURCE:
	// ext4 lets either write past a project quota (fs/quota/dquot.c
	// ignore_hardlimit), so a root fileshare would not be held to the volumes
	// this process sizes.
	ClientUID int64 `hcl:"client_uid"`
	// Group owns every volume root (root:<group>, mode 2770): fileshare writes
	// through it and never OWNS a volume, because the owner of a directory may
	// clear its project id without any privilege (fs/file_attr.c,
	// vfs_fileattr_set). A name or a number.
	Group string `hcl:"group"`
	// MaxVolume is the largest quota one volume may have: "10T", "500G",
	// "1048576". Above it is OUT_OF_RANGE.
	MaxVolume string `hcl:"max_volume"`
	// StateFile is where the volumes this process created are recorded --
	// the btrfs subvolume ids, the XFS/ext4 project ids it allocated -- so
	// that it knows, after a restart, what is its own.
	StateFile string        `hcl:"state_file"`
	Parents   []ParentBlock `hcl:"parent,block"`
	// contains filtered or unexported fields
}

Config is the provisioner's own file. It is NOT fileshare's: the two processes have different privileges and different owners, and the file that says which storage may be created belongs to the privileged one.

provisioner {
  listen     = "unix:///run/fileshare-provisioner/provisioner.sock"
  client_uid = 990                       # fileshare's
  group      = "fileshare"
  max_volume = "10T"
  state_file = "/var/lib/fileshare-provisioner/volumes.json"

  parent "tank"  { zfs = "tank/fileshare",  root = "/srv/fileshare/volumes/tank" }
  parent "fast"  { btrfs = "/srv/fileshare/volumes/fast" }
  parent "plain" { xfs = "/srv/fileshare/volumes/plain", project_ids = "100000-199999" }
}

func LoadConfig

func LoadConfig(paths []string) (*Config, error)

LoadConfig reads the files named, and every .hcl file in the directories named, as one configuration holding one provisioner block, and checks it.

func (*Config) Check

func (c *Config) Check() error

Check refuses a configuration that names something it cannot mean. It looks at nothing on disk; Run does that, at the start.

type ParentBlock

type ParentBlock struct {
	ID string `hcl:"id,label"`
	// ZFS is the dataset the volumes are children of, and Root the directory
	// they are mounted under: dataset <zfs>/<name> at <root>/<name>.
	ZFS  string `hcl:"zfs,optional"`
	Root string `hcl:"root,optional"`
	// Btrfs, XFS and Ext4 are the directory the volumes are created in.
	Btrfs string `hcl:"btrfs,optional"`
	XFS   string `hcl:"xfs,optional"`
	Ext4  string `hcl:"ext4,optional"`
	// ProjectIDs is the range of XFS/ext4 project ids this parent may give
	// out, "100000-199999". An id outside it is never this provisioner's.
	ProjectIDs string `hcl:"project_ids,optional"`
	// EnableQuota lets the provisioner turn btrfs quotas on when they are
	// off. Without it a btrfs parent with quotas off stops the start:
	// qgroups slow every commit as snapshots multiply (btrfs-progs
	// ch-quota-intro.rst), and that is the operator's choice to make.
	EnableQuota bool `hcl:"enable_quota,optional"`
	// contains filtered or unexported fields
}

A ParentBlock is where volumes may be created, under an id a request names. Exactly one of zfs, btrfs, xfs and ext4.

Jump to

Keyboard shortcuts

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