예제 #1
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)
}
예제 #2
0
파일: qcow.go 프로젝트: postfix/minimega
func (inject *injectData) run() (string, error) {
	if inject.err != nil {
		return "", inject.err
	}

	// create the new img
	p := process("qemu-img")
	cmd := exec.Command(p, "create", "-f", "qcow2", "-b", inject.srcImg, inject.dstImg)

	log.Debug("creating sub image with: %v", cmd)

	result, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("%v\n%v", string(result[:]), 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)

	inject.nbdPath, err = nbd.ConnectImage(inject.dstImg)
	if err != nil {
		return "", err
	}
	defer vmInjectCleanup(mntDir, inject.nbdPath)

	time.Sleep(100 * time.Millisecond) // give time to create partitions

	// decide on a partition
	if inject.partition == "" {
		_, err = os.Stat(inject.nbdPath + "p1")
		if err != nil {
			return "", errors.New("no partitions found")
		}

		_, err = os.Stat(inject.nbdPath + "p2")
		if err == nil {
			return "", errors.New("please specify a partition; multiple found")
		}

		inject.partition = "1"
	}

	// mount new img
	p = process("mount")
	cmd = exec.Command(p, "-w", inject.nbdPath+"p"+inject.partition, mntDir)
	result, err = cmd.CombinedOutput()
	if err != nil {
		// check that ntfs-3g is installed
		p = process("ntfs-3g")
		cmd = exec.Command(p, "--version")
		_, err = cmd.CombinedOutput()
		if err != nil {
			log.Error("ntfs-3g not found, ntfs images unwriteable")
		}

		// mount with ntfs-3g
		p = process("mount")
		cmd = exec.Command(p, "-o", "ntfs-3g", inject.nbdPath+"p"+inject.partition, mntDir)
		result, err = cmd.CombinedOutput()
		if err != nil {
			log.Error("failed to mount partition")
			return "", fmt.Errorf("%v\n%v", string(result[:]), err)
		}
	}

	// copy files/folders into mntDir
	p = process("cp")
	for _, pair := range inject.pairs {
		dir := filepath.Dir(filepath.Join(mntDir, pair.dst))
		os.MkdirAll(dir, 0775)
		cmd = exec.Command(p, "-fr", pair.src, mntDir+"/"+pair.dst)
		result, err = cmd.CombinedOutput()
		if err != nil {
			return "", fmt.Errorf("%v\n%v", string(result[:]), err)
		}
	}

	return inject.dstImg, nil
}
예제 #3
0
파일: disk.go 프로젝트: cdshann/minimega
// 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
}