boot-v2.iso: initial commit
This commit is contained in:
		| @ -1,5 +1,5 @@ | ||||
| # ------------------------------------------------------------------------ | ||||
| from mcluseau/golang-builder:1.18.2 as build | ||||
| from mcluseau/golang-builder:1.18.3 as build | ||||
|  | ||||
| # ------------------------------------------------------------------------ | ||||
| from debian:stretch | ||||
|  | ||||
| @ -8,8 +8,12 @@ import ( | ||||
| 	"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 { | ||||
| @ -189,3 +193,159 @@ menuentry "Direktil" { | ||||
|  | ||||
| 	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() | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,10 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"io" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| func renderKernel(w http.ResponseWriter, r *http.Request, ctx *renderContext) error { | ||||
| @ -15,3 +17,19 @@ func renderKernel(w http.ResponseWriter, r *http.Request, ctx *renderContext) er | ||||
| 	http.ServeFile(w, r, path) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func fetchKernel(out io.Writer, ctx *renderContext) (err error) { | ||||
| 	path, err := ctx.distFetch("kernels", ctx.Host.Kernel) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	in, err := os.Open(path) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	defer in.Close() | ||||
|  | ||||
| 	_, err = io.Copy(out, in) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @ -94,6 +94,10 @@ func (ws *wsHost) register(rws *restful.WebService, alterRB func(*restful.RouteB | ||||
| 		b("bootstrap.tar"). | ||||
| 			Produces(mime.TAR). | ||||
| 			Doc("Get the " + ws.hostDoc + "'s bootstrap seed archive"), | ||||
| 		b("boot-v2.iso"). | ||||
| 			Produces(mime.ISO). | ||||
| 			Param(cmdlineParam). | ||||
| 			Doc("Get the " + ws.hostDoc + "'s boot CD-ROM image (v2)"), | ||||
| 	} { | ||||
| 		alterRB(rb) | ||||
| 		rws.Route(rb) | ||||
| @ -192,6 +196,8 @@ func renderHost(w http.ResponseWriter, r *http.Request, what string, host *local | ||||
| 		err = renderCtx(w, r, ctx, what, buildInitrdV2) | ||||
| 	case "bootstrap.tar": | ||||
| 		err = renderCtx(w, r, ctx, what, buildBootstrap) | ||||
| 	case "boot-v2.iso": | ||||
| 		err = renderCtx(w, r, ctx, what, buildBootISOv2) | ||||
|  | ||||
| 	default: | ||||
| 		http.NotFound(w, r) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user