github.com/Cloud-Foundations/Dominator@v0.3.4/cmd/builder-tool/buildRaw.go (about) 1 // +build linux 2 3 package main 4 5 import ( 6 "fmt" 7 "io" 8 "io/ioutil" 9 "os" 10 "syscall" 11 "time" 12 13 "github.com/Cloud-Foundations/Dominator/imagebuilder/builder" 14 "github.com/Cloud-Foundations/Dominator/lib/decoders" 15 "github.com/Cloud-Foundations/Dominator/lib/filesystem/scanner" 16 "github.com/Cloud-Foundations/Dominator/lib/filesystem/util" 17 "github.com/Cloud-Foundations/Dominator/lib/fsutil" 18 "github.com/Cloud-Foundations/Dominator/lib/hash" 19 "github.com/Cloud-Foundations/Dominator/lib/log" 20 "github.com/Cloud-Foundations/Dominator/lib/mbr" 21 "github.com/Cloud-Foundations/Dominator/lib/wsyscall" 22 ) 23 24 const createFlags = os.O_CREATE | os.O_TRUNC | os.O_RDWR 25 26 type dummyHasher struct{} 27 28 func buildRawFromManifestSubcommand(args []string, 29 logger log.DebugLogger) error { 30 if err := buildRawFromManifest(args[0], args[1], logger); err != nil { 31 return fmt.Errorf("error building RAW image from manifest: %s", err) 32 } 33 return nil 34 } 35 36 func buildRawFromManifest(manifestDir, rawFilename string, 37 logger log.DebugLogger) error { 38 var variables map[string]string 39 if *variablesFilename != "" { 40 err := decoders.DecodeFile(*variablesFilename, &variables) 41 if err != nil { 42 return err 43 } 44 } 45 if rawSize < 1<<20 { 46 return fmt.Errorf("rawSize: %d too small", rawSize) 47 } 48 err := syscall.Mount("none", "/", "", syscall.MS_REC|syscall.MS_PRIVATE, "") 49 if err != nil { 50 return fmt.Errorf("error making mounts private: %s", err) 51 } 52 srpcClient := getImageServerClient() 53 tmpFilename := rawFilename + "~" 54 file, err := os.OpenFile(tmpFilename, createFlags, fsutil.PrivateFilePerms) 55 if err != nil { 56 return err 57 } 58 file.Close() 59 defer os.Remove(tmpFilename) 60 if err := os.Truncate(tmpFilename, int64(rawSize)); err != nil { 61 return err 62 } 63 if err := mbr.WriteDefault(tmpFilename, mbr.TABLE_TYPE_MSDOS); err != nil { 64 return err 65 } 66 partition := "p1" 67 loopDevice, err := fsutil.LoopbackSetupAndWaitForPartition(tmpFilename, 68 partition, time.Minute, logger) 69 if err != nil { 70 return err 71 } 72 defer fsutil.LoopbackDeleteAndWaitForPartition(loopDevice, partition, 73 time.Minute, logger) 74 rootDevice := loopDevice + partition 75 rootLabel := "root@test" 76 err = util.MakeExt4fs(rootDevice, rootLabel, nil, 0, logger) 77 if err != nil { 78 return err 79 } 80 rootDir, err := ioutil.TempDir("", "rootfs") 81 if err != nil { 82 return err 83 } 84 defer os.Remove(rootDir) 85 err = wsyscall.Mount(rootDevice, rootDir, "ext4", 0, "") 86 if err != nil { 87 return fmt.Errorf("error mounting: %s", rootDevice) 88 } 89 defer syscall.Unmount(rootDir, 0) 90 logWriter := &logWriterType{} 91 if *alwaysShowBuildLog { 92 fmt.Fprintln(os.Stderr, "Start of build log ==========================") 93 } 94 err = builder.UnpackImageAndProcessManifestWithOptions( 95 srpcClient, 96 builder.BuildLocalOptions{ 97 BindMounts: bindMounts, 98 ManifestDirectory: manifestDir, 99 Variables: variables, 100 }, 101 rootDir, 102 logWriter) 103 if err != nil { 104 if !*alwaysShowBuildLog { 105 fmt.Fprintln(os.Stderr, 106 "Start of build log ==========================") 107 os.Stderr.Write(logWriter.Bytes()) 108 } 109 fmt.Fprintln(os.Stderr, "End of build log ============================") 110 return fmt.Errorf("error processing manifest: %s", err) 111 } 112 if *alwaysShowBuildLog { 113 fmt.Fprintln(os.Stderr, "End of build log ============================") 114 } else { 115 err := fsutil.CopyToFile("build.log", filePerms, &logWriter.buffer, 116 uint64(logWriter.buffer.Len())) 117 if err != nil { 118 return fmt.Errorf("error writing build log: %s", err) 119 } 120 } 121 fs, err := scanner.ScanFileSystem(rootDir, nil, nil, nil, &dummyHasher{}, 122 nil) 123 err = util.MakeBootable(&fs.FileSystem, loopDevice, rootLabel, rootDir, 124 "net.ifnames=0", false, logger) 125 if err != nil { 126 return err 127 } 128 return os.Rename(tmpFilename, rawFilename) 129 } 130 131 func (h *dummyHasher) Hash(reader io.Reader, length uint64) (hash.Hash, error) { 132 return hash.Hash{}, nil 133 }