github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/builder-tool/buildRaw.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "bytes" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "os" 11 "syscall" 12 13 "github.com/Cloud-Foundations/Dominator/imagebuilder/builder" 14 "github.com/Cloud-Foundations/Dominator/lib/filesystem/scanner" 15 "github.com/Cloud-Foundations/Dominator/lib/filesystem/util" 16 "github.com/Cloud-Foundations/Dominator/lib/fsutil" 17 "github.com/Cloud-Foundations/Dominator/lib/hash" 18 "github.com/Cloud-Foundations/Dominator/lib/log" 19 "github.com/Cloud-Foundations/Dominator/lib/mbr" 20 "github.com/Cloud-Foundations/Dominator/lib/wsyscall" 21 ) 22 23 const createFlags = os.O_CREATE | os.O_TRUNC | os.O_RDWR 24 25 type dummyHasher struct{} 26 27 func buildRawFromManifestSubcommand(args []string, 28 logger log.DebugLogger) error { 29 if err := buildRawFromManifest(args[0], args[1], logger); err != nil { 30 return fmt.Errorf("Error building RAW image from manifest: %s", err) 31 } 32 return nil 33 } 34 35 func buildRawFromManifest(manifestDir, rawFilename string, 36 logger log.DebugLogger) error { 37 if rawSize < 1<<20 { 38 return fmt.Errorf("rawSize: %d too small", rawSize) 39 } 40 err := syscall.Mount("none", "/", "", syscall.MS_REC|syscall.MS_PRIVATE, "") 41 if err != nil { 42 return fmt.Errorf("error making mounts private: %s", err) 43 } 44 srpcClient := getImageServerClient() 45 buildLog := &bytes.Buffer{} 46 tmpFilename := rawFilename + "~" 47 file, err := os.OpenFile(tmpFilename, createFlags, fsutil.PrivateFilePerms) 48 if err != nil { 49 return err 50 } 51 file.Close() 52 defer os.Remove(tmpFilename) 53 if err := os.Truncate(tmpFilename, int64(rawSize)); err != nil { 54 return err 55 } 56 if err := mbr.WriteDefault(tmpFilename, mbr.TABLE_TYPE_MSDOS); err != nil { 57 return err 58 } 59 loopDevice, err := fsutil.LoopbackSetup(tmpFilename) 60 if err != nil { 61 return err 62 } 63 defer fsutil.LoopbackDelete(loopDevice) 64 rootDevice := loopDevice + "p1" 65 rootLabel := "root@test" 66 err = util.MakeExt4fs(rootDevice, rootLabel, nil, 0, logger) 67 if err != nil { 68 return err 69 } 70 rootDir, err := ioutil.TempDir("", "rootfs") 71 if err != nil { 72 return err 73 } 74 defer os.Remove(rootDir) 75 err = wsyscall.Mount(rootDevice, rootDir, "ext4", 0, "") 76 if err != nil { 77 return fmt.Errorf("error mounting: %s", rootDevice) 78 } 79 defer syscall.Unmount(rootDir, 0) 80 err = builder.UnpackImageAndProcessManifest(srpcClient, manifestDir, 81 rootDir, bindMounts, buildLog) 82 if err != nil { 83 fmt.Fprintf(os.Stderr, "Error processing manifest: %s\n", err) 84 io.Copy(os.Stderr, buildLog) 85 os.Exit(1) 86 } 87 fs, err := scanner.ScanFileSystem(rootDir, nil, nil, nil, &dummyHasher{}, 88 nil) 89 err = util.MakeBootable(&fs.FileSystem, loopDevice, rootLabel, rootDir, 90 "net.ifnames=0", false, logger) 91 if err != nil { 92 return err 93 } 94 err = fsutil.CopyToFile("build.log", filePerms, buildLog, 95 uint64(buildLog.Len())) 96 if err != nil { 97 fmt.Fprintf(os.Stderr, "Error writing build log: %s\n", err) 98 os.Exit(1) 99 } 100 return os.Rename(tmpFilename, rawFilename) 101 } 102 103 func (h *dummyHasher) Hash(reader io.Reader, length uint64) (hash.Hash, error) { 104 return hash.Hash{}, nil 105 }