2024-07-06 13:36:48 +00:00
|
|
|
package daemon
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-07-13 12:34:06 +00:00
|
|
|
"errors"
|
2024-07-06 13:36:48 +00:00
|
|
|
"fmt"
|
|
|
|
"isle/bootstrap"
|
2024-07-13 12:34:06 +00:00
|
|
|
"isle/secrets"
|
2024-07-06 13:36:48 +00:00
|
|
|
|
|
|
|
"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
|
|
|
|
opts Opts
|
|
|
|
|
|
|
|
pmuxCancelFn context.CancelFunc
|
|
|
|
pmuxStoppedCh chan struct{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewChildren initialized and returns a Children instance. If initialization
|
|
|
|
// fails an error is returned.
|
|
|
|
func NewChildren(
|
|
|
|
ctx context.Context,
|
|
|
|
logger *mlog.Logger,
|
2024-07-13 12:34:06 +00:00
|
|
|
binDirPath string,
|
|
|
|
secretsStore secrets.Store,
|
2024-07-06 13:36:48 +00:00
|
|
|
daemonConfig Config,
|
2024-07-14 10:19:39 +00:00
|
|
|
garageAdminToken string,
|
2024-07-06 13:36:48 +00:00
|
|
|
hostBootstrap bootstrap.Bootstrap,
|
|
|
|
opts *Opts,
|
|
|
|
) (
|
|
|
|
*Children, error,
|
|
|
|
) {
|
|
|
|
opts = opts.withDefaults()
|
|
|
|
|
2024-07-13 12:34:06 +00:00
|
|
|
logger.Info(ctx, "Loading secrets")
|
2024-07-14 09:58:39 +00:00
|
|
|
garageRPCSecret, err := getGarageRPCSecret(ctx, secretsStore)
|
2024-07-13 12:34:06 +00:00
|
|
|
if err != nil && !errors.Is(err, secrets.ErrNotFound) {
|
|
|
|
return nil, fmt.Errorf("loading garage RPC secret: %w", err)
|
|
|
|
}
|
|
|
|
|
2024-07-06 13:36:48 +00:00
|
|
|
pmuxCtx, pmuxCancelFn := context.WithCancel(context.Background())
|
|
|
|
|
|
|
|
c := &Children{
|
|
|
|
logger: logger,
|
|
|
|
opts: *opts,
|
|
|
|
pmuxCancelFn: pmuxCancelFn,
|
|
|
|
pmuxStoppedCh: make(chan struct{}),
|
|
|
|
}
|
|
|
|
|
2024-07-13 12:34:06 +00:00
|
|
|
pmuxConfig, err := c.newPmuxConfig(
|
2024-07-14 10:19:39 +00:00
|
|
|
ctx,
|
|
|
|
garageRPCSecret,
|
|
|
|
binDirPath,
|
|
|
|
daemonConfig,
|
|
|
|
garageAdminToken,
|
|
|
|
hostBootstrap,
|
2024-07-13 12:34:06 +00:00
|
|
|
)
|
2024-07-06 13:36:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("generating pmux config: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
defer close(c.pmuxStoppedCh)
|
|
|
|
pmuxlib.Run(pmuxCtx, c.opts.Stdout, c.opts.Stderr, pmuxConfig)
|
|
|
|
c.logger.Debug(pmuxCtx, "pmux stopped")
|
|
|
|
}()
|
|
|
|
|
2024-07-14 10:19:39 +00:00
|
|
|
initErr := c.postPmuxInit(
|
|
|
|
ctx, daemonConfig, garageAdminToken, hostBootstrap,
|
|
|
|
)
|
2024-07-06 13:36:48 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.pmuxCancelFn()
|
|
|
|
<-c.pmuxStoppedCh
|
|
|
|
return nil
|
|
|
|
}
|