github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/containers/utils/image-creator/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"path"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/emc-advanced-dev/pkg/errors"
    12  
    13  	log "github.com/sirupsen/logrus"
    14  
    15  	"io"
    16  
    17  	unikos "github.com/solo-io/unik/pkg/os"
    18  	"github.com/pborman/uuid"
    19  )
    20  
    21  type volumeslice []unikos.RawVolume
    22  
    23  func (m *volumeslice) String() string {
    24  
    25  	return fmt.Sprintf("%v", ([]unikos.RawVolume)(*m))
    26  }
    27  
    28  // The second method is Set(value string) error
    29  func (m *volumeslice) Set(value string) error {
    30  
    31  	volparts := strings.Split(value, ",")
    32  
    33  	if (len(volparts) != 1) && (len(volparts) != 2) {
    34  		return errors.New("bad format", nil)
    35  	}
    36  
    37  	folder := volparts[0]
    38  
    39  	var size int64
    40  	if len(volparts) >= 2 {
    41  		size, _ = strconv.ParseInt(volparts[1], 0, 64)
    42  	}
    43  	*m = append(*m, unikos.RawVolume{Path: folder, Size: size})
    44  
    45  	return nil
    46  }
    47  
    48  func verifyPreConditions() {
    49  	_, err := os.Stat("/dev/loop0")
    50  	if os.IsNotExist(err) {
    51  		log.Fatal("No loop device found. if running from docker use \"--privileged -v /dev/:/dev/\"")
    52  	}
    53  }
    54  
    55  func main() {
    56  	log.SetLevel(log.DebugLevel)
    57  
    58  	var volumes volumeslice
    59  	partitionTable := flag.String("p", "true", "create partition table")
    60  	buildcontextdir := flag.String("d", "/opt/vol", "build context. relative volume names are relative to that")
    61  	volType := flag.String("t", "ext2", "type of volume 'mirage-fat', 'fat' or 'ext2'")
    62  	flag.Var(&volumes, "v", "volumes folder[,size]")
    63  	out := flag.String("o", "", "base name of output file")
    64  
    65  	flag.Parse()
    66  
    67  	if len(volumes) == 0 {
    68  		log.Fatal("No volumes provided")
    69  	}
    70  
    71  	imgFile := path.Join(*buildcontextdir, "data.image."+uuid.New())
    72  	defer os.Remove(imgFile)
    73  
    74  	for i := range volumes {
    75  		volumes[i].Path = path.Join(*buildcontextdir, volumes[i].Path)
    76  	}
    77  
    78  	verifyPreConditions()
    79  	if *volType == "mirage-fat" {
    80  		if *partitionTable == "true" {
    81  			log.Fatal("Can't create mirage-fat volume with a partition table.")
    82  		}
    83  
    84  		if len(volumes) != 1 {
    85  			log.Fatal("Can only create one volume with no partition table")
    86  		}
    87  		volume := volumes[0]
    88  		if volume.Size == 0 {
    89  			var err error
    90  			volume.Size, err = unikos.GetDirSize(volume.Path)
    91  			if err != nil {
    92  				log.Panic(err)
    93  			}
    94  		}
    95  
    96  		sizeKb := volume.Size >> 10
    97  		// add 8 kb to handle edge cases
    98  		sizeKb += 8
    99  
   100  		log.WithFields(log.Fields{"sizeKb": sizeKb, "size": volume.Size}).Info("Creating mirage fat volume.")
   101  
   102  		err := unikos.RunLogCommand("fat", "create", imgFile, fmt.Sprintf("%d%s", sizeKb, "KiB"))
   103  		if err != nil {
   104  			log.Panic(err)
   105  		}
   106  
   107  		if volume.Path != "" {
   108  			err := unikos.RunLogCommand("/bin/bash", "-c", fmt.Sprintf("cd \"%s\" && fat add %s *", volume.Path, imgFile))
   109  			if err != nil {
   110  				log.Panic(err)
   111  			}
   112  		}
   113  
   114  	} else {
   115  
   116  		if *partitionTable == "true" {
   117  			log.Info("Creating volume with partition table")
   118  
   119  			diskLabelGen := func(device string) unikos.Partitioner { return &unikos.DiskLabelPartioner{device} }
   120  
   121  			// rump so we use disklabel
   122  			err := unikos.CreateVolumes(imgFile, *volType, []unikos.RawVolume(volumes), diskLabelGen)
   123  
   124  			if err != nil {
   125  				panic(err)
   126  			}
   127  		} else {
   128  			log.Info("Creating volume with no partition table")
   129  
   130  			if len(volumes) != 1 {
   131  				log.Fatal("Can only create one volume with no partition table")
   132  			}
   133  
   134  			err := unikos.CreateSingleVolume(imgFile, *volType, volumes[0])
   135  
   136  			if err != nil {
   137  				panic(err)
   138  			}
   139  		}
   140  	}
   141  
   142  	src, err := os.Open(imgFile)
   143  	if err != nil {
   144  		log.Fatal("failed to open produced image file "+imgFile, err)
   145  	}
   146  	outFile := path.Join(*buildcontextdir, *out)
   147  	dst, err := os.OpenFile(outFile, os.O_RDWR, 0)
   148  	if err != nil {
   149  		log.Fatal("failed to open target output file "+outFile, err)
   150  	}
   151  	n, err := io.Copy(dst, src)
   152  	if err != nil {
   153  		log.Fatal("failed copying produced image file to target output file", err)
   154  	}
   155  	log.Infof("wrote %d bytes to disk", n)
   156  }