// Inject files into a qcow // Alternatively, this function can also return a qcow2 backing file's name func cliVmInject(c *minicli.Command) *minicli.Response { resp := &minicli.Response{Host: hostname} // Load nbd err := nbd.Modprobe() if err != nil { resp.Error = err.Error() return resp } inject := parseInject(c) if inject.dstImg == "" { // Create new snapshot for image dstImg, err := ioutil.TempFile(*f_iomBase, "snapshot") if err != nil { inject.err = errors.New("could not create a dst image") } else { inject.dstImg = dstImg.Name() } } log.Debug("destination image: %v", inject.dstImg) resp.Response, err = inject.run() if err != nil { resp.Error = err.Error() } return resp }
// Buildqcow2 creates a qcow2 image using qemu-img, qemu-nbd, fdisk, mkfs.ext4, // cp, and extlinux. func Buildqcow2(buildPath string, c vmconfig.Config) error { targetName := strings.Split(filepath.Base(c.Path), ".")[0] log.Debugln("using target name:", targetName) err := nbd.Modprobe() if err != nil { return err } wd, err := os.Getwd() if err != nil { return err } // Final qcow2 target targetqcow2 := fmt.Sprintf("%v/%v.qcow2", wd, targetName) // Temporary file for building qcow2 file, will be renamed to targetqcow2 tmpqcow2 := fmt.Sprintf("%v/%v.qcow2.tmp", wd, targetName) err = createQcow2(tmpqcow2, *f_qcowsize) if err != nil { return err } // Cleanup our temporary building file defer func() { // Check if file exists if _, err := os.Stat(tmpqcow2); err == nil { if err = os.Remove(tmpqcow2); err != nil { log.Errorln(err) } } }() dev, err := nbd.ConnectImage(tmpqcow2) if err != nil { return err } // Disconnect from the nbd device defer func() { if err := nbd.DisconnectDevice(dev); err != nil { log.Errorln(err) } }() err = partitionQcow2(dev) if err != nil { return err } err = formatQcow2(dev + "p1") if err != nil { return err } mountPath, err := mountQcow2(dev + "p1") if err != nil { return err } err = copyQcow2(buildPath, mountPath) if err != nil { err2 := umountQcow2(mountPath) if err2 != nil { log.Errorln(err2) } return err } err = extlinux(mountPath) if err != nil { err2 := umountQcow2(mountPath) if err2 != nil { log.Errorln(err2) } return err } err = umountQcow2(mountPath) if err != nil { return err } err = extlinuxMBR(dev, *f_mbr) if err != nil { return err } return os.Rename(tmpqcow2, targetqcow2) }
// diskInject injects files into a disk image. dst/partition specify the image // and the partition number, pairs is the dst, src filepaths. options can be // used to supply mount arguments. func diskInject(dst, partition string, pairs map[string]string, options []string) error { // Load nbd if err := nbd.Modprobe(); err != nil { return err } // create a tmp mount point mntDir, err := ioutil.TempDir(*f_base, "dstImg") if err != nil { return err } log.Debug("temporary mount point: %v", mntDir) nbdPath, err := nbd.ConnectImage(dst) if err != nil { return err } defer diskInjectCleanup(mntDir, nbdPath) time.Sleep(100 * time.Millisecond) // give time to create partitions // decide on a partition if partition == "" { _, err = os.Stat(nbdPath + "p1") if err != nil { return errors.New("no partitions found") } _, err = os.Stat(nbdPath + "p2") if err == nil { return errors.New("please specify a partition; multiple found") } partition = "1" } // mount new img var path string if partition == "none" { path = nbdPath } else { path = nbdPath + "p" + partition } // we use mount(8), because the mount syscall (mount(2)) requires we // populate the fstype field, which we don't know args := []string{"mount"} if len(options) != 0 { args = append(args, options...) args = append(args, path, mntDir) } else { args = []string{"mount", "-w", path, mntDir} } log.Debug("mount args: %v", args) _, err = processWrapper(args...) if err != nil { // check that ntfs-3g is installed _, err = processWrapper("ntfs-3g", "--version") if err != nil { log.Error("ntfs-3g not found, ntfs images unwriteable") } // mount with ntfs-3g out, err := processWrapper("mount", "-o", "ntfs-3g", path, mntDir) if err != nil { log.Error("failed to mount partition") return fmt.Errorf("%v: %v", out, err) } } // copy files/folders into mntDir for dst, src := range pairs { dir := filepath.Dir(filepath.Join(mntDir, dst)) os.MkdirAll(dir, 0775) out, err := processWrapper("cp", "-fr", src, filepath.Join(mntDir, dst)) if err != nil { return fmt.Errorf("%v: %v", out, err) } } return nil }