isle/go/daemon/children/garage.go

179 lines
3.8 KiB
Go
Raw Permalink Normal View History

package children
import (
"context"
"errors"
"fmt"
"isle/bootstrap"
"isle/daemon/daecommon"
"isle/garage"
"isle/garage/garagesrv"
"net"
"path/filepath"
"strconv"
"code.betamike.com/micropelago/pmux/pmuxlib"
2024-06-22 15:49:56 +00:00
"dev.mediocregopher.com/mediocre-go-lib.git/mctx"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
)
func garageAdminClientLogger(logger *mlog.Logger) *mlog.Logger {
return logger.WithNamespace("garageAdminClient")
}
func waitForGarage(
ctx context.Context,
logger *mlog.Logger,
networkConfig daecommon.NetworkConfig,
adminToken string,
hostBootstrap bootstrap.Bootstrap,
) error {
allocs := networkConfig.Storage.Allocations
if len(allocs) == 0 {
return nil
}
adminClientLogger := garageAdminClientLogger(logger)
for _, alloc := range allocs {
adminAddr := net.JoinHostPort(
hostBootstrap.ThisHost().IP().String(),
strconv.Itoa(alloc.AdminPort),
)
adminClient := garage.NewAdminClient(
adminClientLogger, adminAddr, adminToken,
)
ctx := mctx.Annotate(
ctx, "garageAdminAddr", adminAddr, "garageDataPath", alloc.DataPath,
)
logger.Info(ctx, "Waiting for garage instance to be healthy")
if err := adminClient.Wait(ctx); err != nil {
return fmt.Errorf("waiting for garage instance %q to start up: %w", adminAddr, err)
}
adminClient.Close()
}
return nil
}
func garageWriteChildConfig(
ctx context.Context,
logger *mlog.Logger,
rpcSecret, runtimeDirPath, adminToken string,
hostBootstrap bootstrap.Bootstrap,
alloc daecommon.ConfigStorageAllocation,
) (
string, bool, error,
) {
var (
thisHost = hostBootstrap.ThisHost()
id = daecommon.BootstrapGarageHostForAlloc(thisHost, alloc).ID
node = garage.LocalNode{
RemoteNode: garage.RemoteNode{
ID: id,
IP: thisHost.IP().String(),
RPCPort: alloc.RPCPort,
S3APIPort: alloc.S3APIPort,
},
AdminPort: alloc.AdminPort,
}
garageTomlPath = filepath.Join(
runtimeDirPath, fmt.Sprintf("garage-%d.toml", alloc.RPCPort),
)
)
changed, err := garagesrv.WriteGarageTomlFile(
ctx,
logger,
garageTomlPath,
garagesrv.GarageTomlData{
MetaPath: alloc.MetaPath,
DataPath: alloc.DataPath,
RPCSecret: rpcSecret,
AdminToken: adminToken,
LocalNode: node,
BootstrapPeers: hostBootstrap.GarageNodes(),
},
)
if err != nil {
return "", false, fmt.Errorf(
"creating garage.toml file at %q: %w", garageTomlPath, err,
)
}
return garageTomlPath, changed, nil
}
func garagePmuxProcName(alloc daecommon.ConfigStorageAllocation) string {
return fmt.Sprintf("garage-%d", alloc.RPCPort)
}
func garagePmuxProc(
ctx context.Context,
logger *mlog.Logger,
binDirPath string,
procName string,
childConfigPath string,
) *pmuxlib.Process {
cfg := pmuxlib.ProcessConfig{
Cmd: filepath.Join(binDirPath, "garage"),
Args: []string{"-c", childConfigPath, "server"},
}
cfg = withPmuxLoggers(ctx, logger, procName, cfg)
return pmuxlib.NewProcess(cfg)
}
func garagePmuxProcs(
ctx context.Context,
logger *mlog.Logger,
rpcSecret, runtimeDirPath, binDirPath string,
networkConfig daecommon.NetworkConfig,
adminToken string,
hostBootstrap bootstrap.Bootstrap,
) (
map[string]*pmuxlib.Process, error,
) {
var (
pmuxProcs = map[string]*pmuxlib.Process{}
allocs = networkConfig.Storage.Allocations
)
if len(allocs) > 0 && rpcSecret == "" {
return nil, errors.New("Storage allocations defined, but garage RPC secret is not available")
}
for _, alloc := range allocs {
childConfigPath, _, err := garageWriteChildConfig(
ctx,
logger,
rpcSecret, runtimeDirPath, adminToken,
hostBootstrap,
alloc,
)
if err != nil {
return nil, fmt.Errorf("writing child config file for alloc %+v: %w", alloc, err)
}
procName := garagePmuxProcName(alloc)
pmuxProcs[procName] = garagePmuxProc(
ctx, logger, binDirPath, procName, childConfigPath,
)
}
return pmuxProcs, nil
}