Files
colima/daemon/daemon.go
T
Abiola Ibrahim 44716fac27 net: add support for bridge mode
Signed-off-by: Abiola Ibrahim <git@abiosoft.com>
2025-08-19 20:08:12 +01:00

138 lines
3.7 KiB
Go

package daemon
import (
"context"
"fmt"
"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/daemon/process"
"github.com/abiosoft/colima/daemon/process/inotify"
"github.com/abiosoft/colima/daemon/process/vmnet"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/util"
"github.com/abiosoft/colima/util/fsutil"
"github.com/abiosoft/colima/util/osutil"
)
// Manager handles running background processes.
type Manager interface {
Start(context.Context, config.Config) error
Stop(context.Context, config.Config) error
Running(context.Context, config.Config) (Status, error)
Dependencies(context.Context, config.Config) (deps process.Dependency, root bool)
}
type Status struct {
// Parent process
Running bool
// Subprocesses
Processes []processStatus
}
type processStatus struct {
Name string
Running bool
Error error
}
// NewManager creates a new process manager.
func NewManager(host environment.HostActions) Manager {
return &processManager{
host: host,
}
}
func CtxKey(s string) any { return struct{ key string }{key: s} }
var _ Manager = (*processManager)(nil)
type processManager struct {
host environment.HostActions
}
func (l processManager) Dependencies(ctx context.Context, conf config.Config) (deps process.Dependency, root bool) {
processes := processesFromConfig(conf)
return process.Dependencies(processes...)
}
func (l processManager) init() error {
// dependencies for network
if err := fsutil.MkdirAll(process.Dir(), 0755); err != nil {
return fmt.Errorf("error preparing vmnet: %w", err)
}
return nil
}
func (l processManager) Running(ctx context.Context, conf config.Config) (s Status, err error) {
err = l.host.RunQuiet(osutil.Executable(), "daemon", "status", config.CurrentProfile().ShortName)
if err != nil {
return
}
s.Running = true
ctx = context.WithValue(ctx, process.CtxKeyDaemon(), s.Running)
for _, p := range processesFromConfig(conf) {
pErr := p.Alive(ctx)
s.Processes = append(s.Processes, processStatus{
Name: p.Name(),
Running: pErr == nil,
Error: pErr,
})
}
return
}
func (l processManager) Start(ctx context.Context, conf config.Config) error {
_ = l.Stop(ctx, conf) // this is safe, nothing is done when not running
if err := l.init(); err != nil {
return fmt.Errorf("error preparing daemon directory: %w", err)
}
args := []string{osutil.Executable(), "daemon", "start", config.CurrentProfile().ShortName}
if conf.Network.Address {
args = append(args, "--vmnet")
args = append(args, "--vmnet-mode", conf.Network.Mode)
args = append(args, "--vmnet-interface", conf.Network.BridgeInterface)
}
if conf.MountINotify {
args = append(args, "--inotify")
args = append(args, "--inotify-runtime", conf.Runtime)
for _, mount := range conf.MountsOrDefault() {
p, err := util.CleanPath(mount.Location)
if err != nil {
return fmt.Errorf("error sanitising mount path for inotify: %w", err)
}
args = append(args, "--inotify-dir", p)
}
}
if cli.Settings.Verbose {
args = append(args, "--very-verbose")
}
host := l.host.WithDir(util.HomeDir())
return host.RunQuiet(args...)
}
func (l processManager) Stop(ctx context.Context, conf config.Config) error {
if s, err := l.Running(ctx, conf); err != nil || !s.Running {
return nil
}
return l.host.RunQuiet(osutil.Executable(), "daemon", "stop", config.CurrentProfile().ShortName)
}
func processesFromConfig(conf config.Config) []process.Process {
var processes []process.Process
if conf.Network.Address {
processes = append(processes, vmnet.New(conf.Network.Mode, conf.Network.BridgeInterface))
}
if conf.MountINotify {
processes = append(processes, inotify.New())
}
return processes
}