Example #1
0
// 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
}
Example #2
0
// 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)
}
Example #3
0
// 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
}