Files
spinifex/cmd/lambda-agent/connect.go
T
Josh Siviour 4be471c196 feat(lambda): boot test-link invocations under Firecracker (#1648)
* feat(lambda): deliver guest configuration on a disk the agent erases

* feat(lambda): boot test-link attempts under Firecracker with a kernel hard kill

* fix(lambda): detect the configuration disk by its missing fw_cfg entry

* test(lambda): cover the configuration-disk seal from the agent and state in-package reasons

* fix(lambda): release a Firecracker attempt whose supervisor never started
2026-11-06 11:18:24 +10:00

64 lines
1.8 KiB
Go

package main
import (
"context"
"crypto/tls"
"errors"
"fmt"
"os"
lambdav1 "github.com/mulgadc/spinifex/contracts/lambda/v1"
"github.com/mulgadc/spinifex/spinifex/agents/lambda/hostlink"
)
// Exit statuses: the guest refused to start, the control connection failed,
// or the host closed it.
const (
exitRefused = 2
exitLink = 1
exitClosed = 0
)
type startup struct {
fwCfgDir string
fwCfgRoot string
unload func() error
}
func defaultStartup() startup {
if _, err := os.Stat(hostlink.ConfigDiskRoot); err == nil {
return configDiskStartup(hostlink.ConfigDiskRoot, hostlink.ConfigDiskDevice)
}
return startup{fwCfgDir: hostlink.FwCfgDir, fwCfgRoot: hostlink.FwCfgRoot, unload: hostlink.UnloadFwCfg}
}
// configDiskStartup reads the entries init extracted from the configuration
// disk, and seals by erasing the disk and removing the extracted tree.
func configDiskStartup(root, device string) startup {
return startup{
fwCfgDir: root + "/by_name/" + lambdav1.FwCfgPrefix,
fwCfgRoot: root,
unload: func() error { return hostlink.SealConfigDisk(device, root) },
}
}
// connect loads the identity, seals fw_cfg whether or not the load succeeded,
// then dials the host. Under TLS 1.3 a host refusal is seen only on first read.
func (s startup) connect(ctx context.Context) (*tls.Conn, lambdav1.Scope, int, error) {
id, loadErr := hostlink.LoadIdentity(s.fwCfgDir)
if err := hostlink.SealFwCfg(s.fwCfgRoot, s.unload); err != nil {
return nil, "", exitRefused, errors.Join(loadErr, err)
}
if loadErr != nil {
return nil, "", exitRefused, loadErr
}
conn, err := hostlink.Dial(ctx, id)
if err != nil {
if ctx.Err() != nil {
err = fmt.Errorf("%w: %w", err, context.Cause(ctx))
}
return nil, "", exitLink, err
}
return conn, id.Scope, 0, nil
}