server

package
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Feb 6, 2026 License: Apache-2.0 Imports: 28 Imported by: 0

Documentation

Index

Constants

View Source
const ServerVersion uint64 = 1

ServerVersion is a monotonically increasing version number for lsvd-server. IMPORTANT: This MUST be incremented whenever any changes are made to the lsvd-server code that require running instances to be upgraded. The main miren server will check this version and trigger a graceful restart if the running lsvd-server has an older version.

Variables

This section is empty.

Functions

func SaveServiceConfig

func SaveServiceConfig(path string, cfg *ServiceConfig) error

SaveServiceConfig saves a service config to the given path.

Types

type DebugService

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

DebugService implements the LsvdDebug RPC interface

func NewDebugService

func NewDebugService(server *Server) *DebugService

NewDebugService creates a new debug service

func (*DebugService) GetMetrics

GetMetrics returns reconciliation metrics

func (*DebugService) ListMounts

ListMounts returns all mounts

func (*DebugService) ListVolumes

func (d *DebugService) ListVolumes(ctx context.Context, state *lsvd_v1alpha.LsvdDebugListVolumes) error

ListVolumes returns all volumes

type LSVDDisk

type LSVDDisk interface {
	// Close closes the disk
	Close(ctx context.Context) error

	// Size returns the disk size in bytes
	Size() int64

	// HandleNBD handles NBD protocol on the given connection
	HandleNBD(ctx context.Context, conn net.Conn, clientFile *os.File) error
}

LSVDDisk abstracts LSVD disk operations for NBD handling

type MountController

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

MountController watches lsvd_mount entities and manages NBD devices and mounts

func NewMountController

func NewMountController(log *slog.Logger, dataPath, nodeId string, state *State, ops MountOps) *MountController

NewMountController creates a new mount controller. The controller is created without an EntityAccessClient so that local system reconciliation (ReconcileWithSystem) can run immediately at startup, even if the entity server is unavailable. Call SetEAC after establishing a connection to the entity server to enable entity-based reconciliation.

func (*MountController) Index

func (c *MountController) Index() entity.Attr

Index returns the entity index attribute for watching mount entities on this node.

func (*MountController) Init

func (c *MountController) Init(ctx context.Context) error

Init implements controller.ReconcileControllerI.

func (*MountController) Reconcile

func (c *MountController) Reconcile(ctx context.Context, mount *storage_v1alpha.LsvdMount, meta *entity.Meta) error

Reconcile implements controller.ReconcileControllerI.

func (*MountController) ReconcileWithEntities

func (c *MountController) ReconcileWithEntities(ctx context.Context) error

ReconcileWithEntities reconciles local state with entity server

func (*MountController) ReconcileWithSystem

func (c *MountController) ReconcileWithSystem(ctx context.Context) error

ReconcileWithSystem reconciles mount state with the actual system

func (*MountController) SetEAC

SetEAC sets the EntityAccessClient for entity server communication. This is separate from construction because the controller must be usable for local system reconciliation before the entity server connection is established — ensuring disks remain available even during entity server outages.

func (*MountController) Shutdown

func (c *MountController) Shutdown()

Shutdown unmounts filesystems, disconnects NBD devices, and cleans up handlers.

type MountOps

type MountOps interface {
	// CreateDir creates a directory with the specified permissions
	CreateDir(path string, perm os.FileMode) error

	// RemoveFile removes a file
	RemoveFile(path string) error

	// NBDLoopback sets up an NBD loopback device
	// Returns: index, conn, clientFile, cleanup function, error
	NBDLoopback(ctx context.Context, sizeBytes uint64) (uint32, net.Conn, *os.File, func() error, error)

	// NBDStatus checks the status of an NBD device
	NBDStatus(idx uint32) error

	// NBDDisconnect disconnects an NBD device
	NBDDisconnect(idx uint32) error

	// CreateDeviceNode creates a block device node
	CreateDeviceNode(path string, nbdIndex uint32) error

	// Mount mounts a device at the specified path
	Mount(device, mountPath, filesystem string, readOnly bool) error

	// Unmount unmounts a path
	Unmount(path string) error

	// IsMounted checks if a path is a mount point
	IsMounted(path string) bool

	// IsFormatted checks if a device has a filesystem
	IsFormatted(device, filesystem string) (bool, error)

	// FormatDevice formats a device with the specified filesystem
	FormatDevice(ctx context.Context, device, filesystem string) error

	// OpenLSVDDisk opens an LSVD disk for the given volume.
	// If remoteOnly is true, the disk uses only remote cloud storage (no local).
	// The leaseNonce is passed to the segment access for write operations.
	OpenLSVDDisk(ctx context.Context, diskPath, volumeId string, remoteOnly bool, leaseNonce string) (LSVDDisk, error)

	// AcquireVolumeLease acquires a lease from the cloud for exclusive access.
	// Returns the lease nonce, or empty string if cloud auth is not configured.
	AcquireVolumeLease(ctx context.Context, volumeId string, metadata map[string]any) (string, error)

	// ReleaseVolumeLease releases a lease from the cloud.
	// Does nothing if cloud auth is not configured or nonce is empty.
	ReleaseVolumeLease(ctx context.Context, volumeId, nonce string) error
}

MountOps abstracts OS operations for mount management. This interface enables testing without requiring actual NBD, device, or mount operations.

func NewRealMountOps

func NewRealMountOps(log *slog.Logger, authClient *cloudauth.AuthClient, cloudURL string) MountOps

NewRealMountOps creates a MountOps that performs real OS operations. If authClient is non-nil, disks are opened with a ReplicaWriter that replicates writes to the remote cloud.

type MountState

type MountState struct {
	// EntityId is the ID of the lsvd_mount entity
	EntityId string `json:"entity_id"`

	// VolumeId is the ID of the lsvd_volume entity
	VolumeId string `json:"volume_id"`

	// NbdIndex is the NBD device index
	NbdIndex uint32 `json:"nbd_index"`

	// DevicePath is the path to the NBD 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"`

	// LeaseNonce is the volume lease nonce from remote Disk API
	LeaseNonce string `json:"lease_nonce,omitempty"`
}

MountState represents the state of an LSVD mount

type Server

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

Server manages LSVD volumes and mounts by watching entities

func NewServer

func NewServer(log *slog.Logger, dataPath, nodeId, entityServerAddr string, opts ...ServerOption) (*Server, error)

NewServer creates a new LSVD server

func (*Server) Run

func (s *Server) Run(ctx context.Context) error

Run starts the server and blocks until context is cancelled

type ServerOption

type ServerOption func(*serverOptions)

ServerOption configures the server

func WithClientCredentials

func WithClientCredentials(cert, key []byte) ServerOption

WithClientCredentials sets the client TLS credentials for connecting to entity server

func WithCloudAuth

func WithCloudAuth(cloudURL, privateKey string) ServerOption

WithCloudAuth configures cloud authentication for disk replication

func WithSkipVerify

func WithSkipVerify(skip bool) ServerOption

WithSkipVerify skips TLS verification when connecting to entity server

type ServiceConfig

type ServiceConfig struct {
	// ClientCert is the PEM-encoded client certificate
	ClientCert []byte `json:"client_cert,omitempty"`
	// ClientKey is the PEM-encoded client private key
	ClientKey []byte `json:"client_key,omitempty"`
	// CloudURL is the miren.cloud API URL for disk replication
	CloudURL string `json:"cloud_url,omitempty"`
	// PrivateKey is the PEM-encoded private key for cloud authentication
	PrivateKey string `json:"private_key,omitempty"`
}

ServiceConfig holds credentials for connecting to the entity server. This is written by the main server process for lsvd-server to use.

func LoadServiceConfig

func LoadServiceConfig(path string) (*ServiceConfig, error)

LoadServiceConfig loads a service config from the given path.

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 the LSVD server

func LoadState

func LoadState(dataPath string) (*State, error)

LoadState loads state from the data path

func NewState

func NewState() *State

NewState creates a new empty state

func (*State) DeleteMount

func (s *State) DeleteMount(entityId string)

DeleteMount removes a mount state

func (*State) DeleteVolume

func (s *State) DeleteVolume(entityId string)

DeleteVolume removes a volume state

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 LSVD volume ID

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

func (s *State) Save() error

Save persists the state to disk atomically

func (*State) SetMount

func (s *State) SetMount(entityId string, mount *MountState)

SetMount sets a mount state

func (*State) SetPath

func (s *State) SetPath(dataPath string)

SetPath sets the path for the state file

func (*State) SetVolume

func (s *State) SetVolume(entityId string, volume *VolumeState)

SetVolume sets a volume state

type VolumeController

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

VolumeController watches lsvd_volume entities and manages LSVD volumes

func NewVolumeController

func NewVolumeController(log *slog.Logger, dataPath, nodeId string, state *State, ops VolumeOps) *VolumeController

NewVolumeController creates a new volume controller. The controller is created without an EntityAccessClient so that local system reconciliation (ReconcileWithSystem) can run immediately at startup, even if the entity server is unavailable. Call SetEAC after establishing a connection to the entity server to enable entity-based reconciliation.

func (*VolumeController) Index

func (c *VolumeController) Index() entity.Attr

Index returns the entity index attribute for watching volume entities on this node.

func (*VolumeController) Init

func (c *VolumeController) Init(ctx context.Context) error

Init implements controller.ReconcileControllerI.

func (*VolumeController) Reconcile

func (c *VolumeController) Reconcile(ctx context.Context, volume *storage_v1alpha.LsvdVolume, meta *entity.Meta) error

Reconcile implements controller.ReconcileControllerI.

func (*VolumeController) ReconcileWithEntities

func (c *VolumeController) ReconcileWithEntities(ctx context.Context) error

ReconcileWithEntities reconciles local state with entity server

func (*VolumeController) ReconcileWithSystem

func (c *VolumeController) ReconcileWithSystem(ctx context.Context) error

ReconcileWithSystem reconciles volume state with the actual system

func (*VolumeController) SetEAC

SetEAC sets the EntityAccessClient for entity server communication. This is separate from construction because the controller must be usable for local system reconciliation before the entity server connection is established — ensuring disks remain available even during entity server outages.

type VolumeOps

type VolumeOps interface {
	// CreateVolumeDir creates the directory for a volume
	CreateVolumeDir(path string) error

	// RemoveVolumeDir removes a volume directory and all its contents
	RemoveVolumeDir(path string) error

	// VolumePathExists checks if a volume path exists
	VolumePathExists(path string) bool

	// InitLSVDVolume initializes an LSVD volume at the given path.
	// Returns the actual volume ID used (which may differ from the input when
	// cloud auth is configured and the server generates the ID).
	// If remoteOnly is true, the volume is only initialized on the remote cloud
	// (no local storage).
	InitLSVDVolume(ctx context.Context, path, volumeId string, size units.Bytes, metadata map[string]any, remoteOnly bool) (string, error)
}

VolumeOps abstracts OS and LSVD operations for volume management. This interface enables testing without requiring actual filesystem or LSVD operations.

func NewRealVolumeOps

func NewRealVolumeOps(log *slog.Logger, authClient *cloudauth.AuthClient, cloudURL string) VolumeOps

NewRealVolumeOps creates a VolumeOps that performs real OS operations. If authClient is non-nil, volumes are also initialized on the remote cloud.

type VolumeState

type VolumeState struct {
	// EntityId is the ID of the lsvd_volume entity
	EntityId string `json:"entity_id"`

	// VolumeId is the LSVD volume identifier
	VolumeId string `json:"volume_id"`

	// 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"`
}

VolumeState represents the state of an LSVD volume

Jump to

Keyboard shortcuts

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