352 lines
6.6 KiB
Go
352 lines
6.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"github.com/cespare/xxhash"
|
|
)
|
|
|
|
// deprecated
|
|
func buildBootISO(out io.Writer, ctx *renderContext) error {
|
|
tempDir, err := ioutil.TempDir("/tmp", "iso-")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
cp := func(src, dst string) error {
|
|
log.Printf("iso: adding %s as %s", src, dst)
|
|
in, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer in.Close()
|
|
|
|
outPath := filepath.Join(tempDir, dst)
|
|
|
|
if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
out, err := os.Create(outPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer out.Close()
|
|
|
|
_, err = io.Copy(out, in)
|
|
return err
|
|
}
|
|
|
|
err = func() error {
|
|
// grub
|
|
|
|
if err := os.MkdirAll(filepath.Join(tempDir, "grub"), 0755); err != nil {
|
|
return err
|
|
}
|
|
err = ioutil.WriteFile(filepath.Join(tempDir, "grub", "grub.cfg"), []byte(`
|
|
search --set=root --file /config.yaml
|
|
|
|
insmod all_video
|
|
set timeout=3
|
|
|
|
menuentry "Direktil" {
|
|
linux /vmlinuz direktil.boot=DEVNAME=sr0 direktil.boot.fs=iso9660 `+ctx.CmdLine+`
|
|
initrd /initrd
|
|
}
|
|
`), 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
coreImgPath := filepath.Join(tempDir, "grub", "core.img")
|
|
grubCfgPath := filepath.Join(tempDir, "grub", "grub.cfg")
|
|
|
|
cmd := exec.Command("grub-mkstandalone",
|
|
"--format=i386-pc",
|
|
"--output="+coreImgPath,
|
|
"--install-modules=linux normal iso9660 biosdisk memdisk search tar ls",
|
|
"--modules=linux normal iso9660 biosdisk search",
|
|
"--locales=",
|
|
"--fonts=",
|
|
"boot/grub/grub.cfg="+grubCfgPath,
|
|
)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err := cmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
|
|
defer os.Remove(coreImgPath)
|
|
defer os.Remove(grubCfgPath)
|
|
|
|
out, err := os.Create(filepath.Join(tempDir, "grub", "bios.img"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer out.Close()
|
|
|
|
b, err := ioutil.ReadFile("/usr/lib/grub/i386-pc/cdboot.img")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := out.Write(b); err != nil {
|
|
return err
|
|
}
|
|
|
|
b, err = ioutil.ReadFile(coreImgPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := out.Write(b); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// config
|
|
cfgBytes, cfg, err := ctx.Config()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ioutil.WriteFile(filepath.Join(tempDir, "config.yaml"), cfgBytes, 0600)
|
|
|
|
// kernel and initrd
|
|
type distCopy struct {
|
|
Src []string
|
|
Dst string
|
|
}
|
|
|
|
copies := []distCopy{
|
|
{Src: []string{"kernels", ctx.Host.Kernel}, Dst: "vmlinuz"},
|
|
{Src: []string{"initrd", ctx.Host.Initrd}, Dst: "initrd"},
|
|
}
|
|
|
|
// layers
|
|
for _, layer := range cfg.Layers {
|
|
layerVersion := ctx.Host.Versions[layer]
|
|
if layerVersion == "" {
|
|
return fmt.Errorf("layer %q not mapped to a version", layer)
|
|
}
|
|
|
|
copies = append(copies,
|
|
distCopy{
|
|
Src: []string{"layers", layer, layerVersion},
|
|
Dst: filepath.Join("current", "layers", layer+".fs"),
|
|
})
|
|
}
|
|
|
|
for _, copy := range copies {
|
|
outPath, err := ctx.distFetch(copy.Src...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = cp(outPath, copy.Dst)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// build the ISO
|
|
mkisofs, err := exec.LookPath("genisoimage")
|
|
if err != nil {
|
|
mkisofs, err = exec.LookPath("mkisofs")
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd := exec.Command(mkisofs,
|
|
"-quiet",
|
|
"-joliet",
|
|
"-joliet-long",
|
|
"-rock",
|
|
"-translation-table",
|
|
"-no-emul-boot",
|
|
"-boot-load-size", "4",
|
|
"-boot-info-table",
|
|
"-eltorito-boot", "grub/bios.img",
|
|
"-eltorito-catalog", "grub/boot.cat",
|
|
tempDir,
|
|
)
|
|
cmd.Stdout = out
|
|
cmd.Stderr = os.Stderr
|
|
|
|
return cmd.Run()
|
|
}
|
|
|
|
func buildBootISOv2(out io.Writer, ctx *renderContext) (err error) {
|
|
tempDir, err := ioutil.TempDir("/tmp", "iso-v2-")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
buildRes := func(build func(out io.Writer, ctx *renderContext) error, dst string) (err error) {
|
|
log.Printf("iso-v2: building %s", dst)
|
|
|
|
outPath := filepath.Join(tempDir, dst)
|
|
|
|
if err = os.MkdirAll(filepath.Dir(outPath), 0755); err != nil {
|
|
return err
|
|
}
|
|
|
|
out, err := os.Create(outPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer out.Close()
|
|
|
|
err = build(out, ctx)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
err = func() (err error) {
|
|
// grub
|
|
|
|
if err = os.MkdirAll(filepath.Join(tempDir, "grub"), 0755); err != nil {
|
|
return
|
|
}
|
|
|
|
// create a tag file
|
|
bootstrapBytes, _, err := ctx.BootstrapConfig()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
h := xxhash.New()
|
|
fmt.Fprintln(h, ctx.Host.Kernel)
|
|
h.Write(bootstrapBytes)
|
|
|
|
tag := "dkl-" + strconv.FormatUint(h.Sum64(), 32) + ".tag"
|
|
|
|
f, err := os.Create(filepath.Join(tempDir, tag))
|
|
if err != nil {
|
|
return
|
|
}
|
|
f.Write([]byte("direktil marker file\n"))
|
|
f.Close()
|
|
|
|
err = ioutil.WriteFile(filepath.Join(tempDir, "grub", "grub.cfg"), []byte(`
|
|
search --set=root --file /`+tag+`
|
|
|
|
insmod all_video
|
|
set timeout=3
|
|
|
|
menuentry "Direktil" {
|
|
linux /vmlinuz `+ctx.CmdLine+`
|
|
initrd /initrd
|
|
}
|
|
`), 0644)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
coreImgPath := filepath.Join(tempDir, "grub", "core.img")
|
|
grubCfgPath := filepath.Join(tempDir, "grub", "grub.cfg")
|
|
|
|
cmd := exec.Command("grub-mkstandalone",
|
|
"--format=i386-pc",
|
|
"--output="+coreImgPath,
|
|
"--install-modules=linux normal iso9660 biosdisk memdisk search tar ls",
|
|
"--modules=linux normal iso9660 biosdisk search",
|
|
"--locales=",
|
|
"--fonts=",
|
|
"boot/grub/grub.cfg="+grubCfgPath,
|
|
)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err := cmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
|
|
defer os.Remove(coreImgPath)
|
|
defer os.Remove(grubCfgPath)
|
|
|
|
out, err := os.Create(filepath.Join(tempDir, "grub", "bios.img"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer out.Close()
|
|
|
|
b, err := ioutil.ReadFile("/usr/lib/grub/i386-pc/cdboot.img")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := out.Write(b); err != nil {
|
|
return err
|
|
}
|
|
|
|
b, err = ioutil.ReadFile(coreImgPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err := out.Write(b); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// kernel and initrd
|
|
buildRes(fetchKernel, "vmlinuz")
|
|
buildRes(buildInitrdV2, "initrd")
|
|
|
|
// build the ISO
|
|
mkisofs, err := exec.LookPath("genisoimage")
|
|
if err != nil {
|
|
mkisofs, err = exec.LookPath("mkisofs")
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd := exec.Command(mkisofs,
|
|
"-quiet",
|
|
"-joliet",
|
|
"-joliet-long",
|
|
"-rock",
|
|
"-translation-table",
|
|
"-no-emul-boot",
|
|
"-boot-load-size", "4",
|
|
"-boot-info-table",
|
|
"-eltorito-boot", "grub/bios.img",
|
|
"-eltorito-catalog", "grub/boot.cat",
|
|
tempDir,
|
|
)
|
|
cmd.Stdout = out
|
|
cmd.Stderr = os.Stderr
|
|
|
|
return cmd.Run()
|
|
}
|