2022-04-28 01:33:19 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"archive/tar"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
yaml "gopkg.in/yaml.v2"
|
|
|
|
|
|
|
|
"novit.tech/direktil/pkg/cpiocat"
|
|
|
|
)
|
|
|
|
|
|
|
|
func renderBootstrapConfig(w http.ResponseWriter, r *http.Request, ctx *renderContext, asJson bool) (err error) {
|
|
|
|
log.Printf("sending bootstrap config for %q", ctx.Host.Name)
|
|
|
|
|
|
|
|
_, cfg, err := ctx.BootstrapConfig()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if asJson {
|
|
|
|
err = json.NewEncoder(w).Encode(cfg)
|
|
|
|
} else {
|
|
|
|
err = yaml.NewEncoder(w).Encode(cfg)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-08-20 09:08:42 +00:00
|
|
|
func buildInitrd(out io.Writer, ctx *renderContext) (err error) {
|
2022-04-28 01:33:19 +00:00
|
|
|
_, cfg, err := ctx.Config()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
cat := cpiocat.New(out)
|
|
|
|
|
|
|
|
// initrd
|
2023-11-27 14:46:58 +00:00
|
|
|
initrdPath, err := ctx.distFetch("initrd", ctx.Host.Initrd)
|
2022-04-28 01:33:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cat.AppendArchFile(initrdPath)
|
|
|
|
|
|
|
|
// embedded layers (modules)
|
|
|
|
for _, layer := range cfg.Layers {
|
|
|
|
switch layer {
|
|
|
|
case "modules":
|
|
|
|
|
|
|
|
layerVersion := ctx.Host.Versions[layer]
|
|
|
|
modulesPath, err := ctx.distFetch("layers", layer, layerVersion)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
cat.AppendFile(modulesPath, "modules.sqfs")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// config
|
|
|
|
cfgBytes, _, err := ctx.BootstrapConfig()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
cat.AppendBytes(cfgBytes, "config.yaml", 0600)
|
|
|
|
|
|
|
|
// ssh keys
|
|
|
|
// FIXME we want a bootstrap-stage key instead of the real host key
|
2023-12-17 13:40:48 +00:00
|
|
|
for _, format := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
|
|
|
|
cat.AppendBytes(cfg.FileContent("/etc/ssh/ssh_host_"+format+"_key"), "id_"+format, 0600)
|
|
|
|
}
|
2022-04-28 01:33:19 +00:00
|
|
|
|
|
|
|
return cat.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
func buildBootstrap(out io.Writer, ctx *renderContext) (err error) {
|
|
|
|
arch := tar.NewWriter(out)
|
|
|
|
defer arch.Close()
|
|
|
|
|
|
|
|
// config
|
|
|
|
cfgBytes, cfg, err := ctx.Config()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = arch.WriteHeader(&tar.Header{Name: "config.yaml", Size: int64(len(cfgBytes))})
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = arch.Write(cfgBytes)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// layers
|
|
|
|
for _, layer := range cfg.Layers {
|
|
|
|
if layer == "modules" {
|
|
|
|
continue // modules are with the kernel in boot v2
|
|
|
|
}
|
|
|
|
|
|
|
|
layerVersion := ctx.Host.Versions[layer]
|
|
|
|
if layerVersion == "" {
|
|
|
|
return fmt.Errorf("layer %q not mapped to a version", layer)
|
|
|
|
}
|
|
|
|
|
|
|
|
outPath, err := ctx.distFetch("layers", layer, layerVersion)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err := os.Open(outPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
stat, err := f.Stat()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = arch.WriteHeader(&tar.Header{
|
|
|
|
Name: layer + ".fs",
|
|
|
|
Size: stat.Size(),
|
|
|
|
}); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = io.Copy(arch, f)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|