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  }