package daemon import ( "context" "errors" "fmt" "isle/bootstrap" "isle/secrets" "code.betamike.com/micropelago/pmux/pmuxlib" "dev.mediocregopher.com/mediocre-go-lib.git/mlog" ) // Children manages all child processes of a network. Child processes are // comprised of: // - nebula // - dnsmasq // - garage (0 or more, depending on configured storage allocations) type Children struct { logger *mlog.Logger daemonConfig Config opts Opts pmux *pmuxlib.Pmux } // NewChildren initialized and returns a Children instance. If initialization // fails an error is returned. func NewChildren( ctx context.Context, logger *mlog.Logger, binDirPath string, secretsStore secrets.Store, daemonConfig Config, garageAdminToken string, hostBootstrap bootstrap.Bootstrap, opts *Opts, ) ( *Children, error, ) { opts = opts.withDefaults() logger.Info(ctx, "Loading secrets") garageRPCSecret, err := getGarageRPCSecret(ctx, secretsStore) if err != nil && !errors.Is(err, secrets.ErrNotFound) { return nil, fmt.Errorf("loading garage RPC secret: %w", err) } c := &Children{ logger: logger, daemonConfig: daemonConfig, opts: *opts, } pmuxConfig, err := c.newPmuxConfig( ctx, garageRPCSecret, binDirPath, daemonConfig, garageAdminToken, hostBootstrap, ) if err != nil { return nil, fmt.Errorf("generating pmux config: %w", err) } c.pmux = pmuxlib.NewPmux(pmuxConfig, c.opts.Stdout, c.opts.Stderr) initErr := c.postPmuxInit( ctx, daemonConfig, garageAdminToken, hostBootstrap, ) if initErr != nil { logger.Warn(ctx, "failed to initialize Children, shutting down child processes", err) if err := c.Shutdown(); err != nil { panic(fmt.Sprintf( "failed to shut down child processes after initialization"+ " error, there may be zombie children leftover."+ " Original error: %v", initErr, )) } return nil, initErr } return c, nil } // RestartDNSMasq rewrites the dnsmasq config and restarts the process. func (c *Children) RestartDNSMasq(hostBootstrap bootstrap.Bootstrap) error { _, err := dnsmasqWriteConfig( c.opts.EnvVars.RuntimeDirPath, c.daemonConfig, hostBootstrap, ) if err != nil { return fmt.Errorf("writing new dnsmasq config: %w", err) } c.pmux.Restart("dnsmasq") return nil } // RestartNebula rewrites the nebula config and restarts the process. func (c *Children) RestartNebula(hostBootstrap bootstrap.Bootstrap) error { _, err := nebulaWriteConfig( c.opts.EnvVars.RuntimeDirPath, c.daemonConfig, hostBootstrap, ) if err != nil { return fmt.Errorf("writing a new nebula config: %w", err) } c.pmux.Restart("nebula") return nil } // Shutdown blocks until all child processes have gracefully shut themselves // down. // // If this returns an error then it's possible that child processes are // still running and are no longer managed. func (c *Children) Shutdown() error { c.pmux.Stop() return nil }