home

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Nov 7, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package home defines the seam between the invariant core and the environment that holds a grant: a standalone host, a Kubernetes grant Pod, a Slurm allocation. Homes differ only in how signed grants arrive ahead of time, how control-plane liveness is observed, how readiness is published, and which cgroup subtree fiberd owns. A home is conformant iff grant-conform passes against it with pkg/core unmodified.

Index

Constants

This section is empty.

Variables

View Source
var ErrRoundTimeout = errors.New("poll round timed out")

ErrRoundTimeout is the error a poll round reports when it did not answer within one interval.

Functions

func Drive

func Drive(ctx context.Context, h Home, a *core.Core)

Drive feeds the home's grant deliveries into fiberd. On GrantAdded it verifies, lifts any denial and admits. On GrantRemoved it removes. It returns when delivery closes or ctx ends.

Types

type EventKind

type EventKind int

EventKind is what the home delivered.

const (
	// GrantAdded carries a signed token to pre-admit (warm the template
	// before the first Clone). fiberd verifies it like any other.
	GrantAdded EventKind = iota
	// GrantRemoved names a grant the home no longer holds. Its running
	// fibers are released and the UID is refused until every token for
	// it has expired, or the home delivers it again.
	GrantRemoved
)

type GrantEvent

type GrantEvent struct {
	Kind  EventKind
	Token []byte // GrantAdded
	UID   string // GrantRemoved
}

type HealthPoll

type HealthPoll struct {
	// Health is marked on every answered round. Required.
	Health *core.SourceHealth
	// Every is the interval between rounds and the timeout of one round.
	Every time.Duration
	// Clock drives the rounds and stamps the health. Required.
	Clock clock.WithTicker
	// Round asks the control plane once. Required.
	Round func(ctx context.Context) error
	// OnError and OnRecovered report transitions. Either may be nil.
	OnError     func(err error)
	OnRecovered func()
	// contains filtered or unexported fields
}

HealthPoll runs a round against a home's control plane every interval and turns the answers into the issuer health the miss codes key on. A round that answers marks the health sync at the clock's now, unless the poll is paused. A round that fails leaves the health alone, so the health goes stale on its own once the control plane has been silent for the stale TTL.

Run is serial. One round runs at a time, and the next waits for it. A round gets one interval to answer, then its context ends with ErrRoundTimeout as the cause. A Round that honours its context returns the context's error, and the poll reports it as ErrRoundTimeout. A Round that ignores its context delays the next round for as long as it runs. An error of the Round's own is reported as it is, even when the interval ran out while it was being returned.

The poll does not log. OnError is called once per distinct error message, OnRecovered once when a round answers after errors, so a home logs each transition once.

func (*HealthPoll) Once

func (p *HealthPoll) Once(ctx context.Context) error

Once runs one round now and reports its error. Run calls it on every tick, and a test can call it directly.

func (*HealthPoll) Run

func (p *HealthPoll) Run(ctx context.Context)

Run runs a round at once, then one every interval, until ctx ends. It blocks. Run is called once.

func (*HealthPoll) SetPaused

func (p *HealthPoll) SetPaused(paused bool)

SetPaused stops answered rounds from marking the health while paused. The rounds keep running, so error transitions are still reported. A pause waits for a mark in progress, so a health set right after the pause is not marked over by the round that answered just before it.

type Home

type Home interface {
	Name() string
	// Grants delivers grants ahead of traffic and removals. A home
	// that delivers nothing returns a nil channel, and grants then arrive only
	// inside Clone requests. On a home that holds a grant of its own,
	// Clone admits that grant instead of the token it carries.
	Grants(ctx context.Context) (<-chan GrantEvent, error)
	// Health is the control-plane liveness the miss codes key on.
	Health() *core.SourceHealth
	// CgroupRoot is the delegated cgroup v2 subtree the runtime may carve.
	CgroupRoot() string
	// PublishReady tells the home's control plane that the grant's
	// template is warm (a readiness gate, a status stream, nothing).
	PublishReady(ctx context.Context, grantUID string, ready bool) error
	// Scope is what this home asserts about where it runs (namespace,
	// service account, DRA claim, job). Stamped on audit records;
	// nil on a standalone host. Scope is visible, never a third validity
	// term: a home that loses it revokes fences (Core.BumpEpoch) or
	// grants (GrantRemoved), and the core keeps min(lease, fence).
	Scope() []core.ScopeClaim
	// Devices provisions the grant's device channel, the devices its
	// engine may drive, and returns how to release it: a static set here,
	// a DRA claim under Kubernetes, the allocation's GRES under Slurm.
	Devices(ctx context.Context, g core.Grant) (core.DeviceChannel, func(), error)
	// Run drives whatever the home needs in the background (issuer polls,
	// watches) until ctx ends.
	Run(ctx context.Context)
}

Home is what cmd/fiberd wires around fiberd.

type ReadyGate

type ReadyGate struct {
	// Publish sends the gate. warm holds the UIDs of the grants with a
	// warm template, sorted, and is empty when none has. Required.
	Publish func(ctx context.Context, warm []string) error
	// contains filtered or unexported fields
}

ReadyGate tracks which grants have a warm template and publishes the one readiness fact a control plane wants, "any template is warm", through Publish. Publish is called on the first PublishReady and whenever that fact flips. A failed publish leaves the published state as it was, so the next PublishReady or the next Republish sends it again.

One publish is in flight at a time and no lock is held across it. A PublishReady that arrives while another is in flight records its change and returns, and the publisher in flight sends the newest state once its call returns. The control plane therefore sees states in the order they were decided, never an older state after a newer one.

The gate does not log. Republish reports whether the outcome changed so the home logs each distinct failure, and the recovery, once.

func (*ReadyGate) PublishReady

func (g *ReadyGate) PublishReady(ctx context.Context, grantUID string, ready bool) error

PublishReady records that grantUID's template is warm, or no longer is, and publishes the gate when that flips it. It returns the publish error, or nil when nothing had to be sent or another publish in flight will send it.

func (*ReadyGate) Ready

func (g *ReadyGate) Ready() bool

Ready reports whether any grant has a warm template.

func (*ReadyGate) Republish

func (g *ReadyGate) Republish(ctx context.Context) (changed bool, err error)

Republish sends the gate again when the last publish failed, or when the control plane has not been told yet. Before the first PublishReady there is nothing to republish. changed is true when the outcome differs from the last one, that is a new error message, or a success after a failure.

type ScopeLossQueue

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

ScopeLossQueue hands scope-loss reasons to one callback, in the order they were detected, each reason once per lifetime. A home detects a loss inside a poll round and calls Lose. Delivery happens on the one goroutine Run owns, with the context Run was given, so a slow callback (an epoch bump that waits for fibers) never stalls a poll round and outlives the round that found the loss. Reasons detected before OnScopeLost is called wait in the queue and are delivered in order once a callback exists. The queue does not log. Lose reports whether a reason is new so the home can.

The zero value is ready to use.

func (*ScopeLossQueue) Lose

func (q *ScopeLossQueue) Lose(reason string) bool

Lose queues reason for delivery and reports whether it is new. A reason already seen is dropped.

func (*ScopeLossQueue) OnScopeLost

func (q *ScopeLossQueue) OnScopeLost(fn func(ctx context.Context, reason string))

OnScopeLost sets the callback. A nil fn is ignored, and the queued reasons keep waiting. Setting a callback wakes delivery.

func (*ScopeLossQueue) Pending

func (q *ScopeLossQueue) Pending() int

Pending is how many reasons wait for delivery.

func (*ScopeLossQueue) Run

func (q *ScopeLossQueue) Run(ctx context.Context)

Run delivers queued reasons until ctx ends. It blocks, so the caller gives it a goroutine and waits for it to return. It is the only goroutine that ever calls the callback. Run is called once.

Directories

Path Synopsis
Package grantdir delivers grants to every file-fed home from a directory polled for *.jwt files.
Package grantdir delivers grants to every file-fed home from a directory polled for *.jwt files.
Package kubernetes is fiberd's home in a Kubernetes grant Pod, where fiberd is the Pod's one container.
Package kubernetes is fiberd's home in a Kubernetes grant Pod, where fiberd is the Pod's one container.
fake
Package fake serves the Kubernetes home's slice of the API from memory, for tests that need no API server.
Package fake serves the Kubernetes home's slice of the API from memory, for tests that need no API server.
Package standalone is the home for a plain host: no scheduler, no kubelet.
Package standalone is the home for a plain host: no scheduler, no kubelet.

Jump to

Keyboard shortcuts

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