lxd/storage_ceph_utils.go
func (s *storageCeph) copyWithSnapshots(sourceVolumeName string,
	targetVolumeName string, sourceParentSnapshot string) error {
	logger.Debugf(`Creating non-sparse copy of RBD storage volume "%s to "%s"`, sourceVolumeName, targetVolumeName)

	args := []string{
		"export-diff",
		"--id", s.UserName,
		"--cluster", s.ClusterName,
		sourceVolumeName,
	}

	if sourceParentSnapshot != "" {
		args = append(args, "--from-snap", sourceParentSnapshot)
	}

	// redirect output to stdout
	args = append(args, "-")

	rbdSendCmd := exec.Command("rbd", args...)
	rbdRecvCmd := exec.Command(
		"rbd",
		"--id", s.UserName,
		"import-diff",
		"--cluster", s.ClusterName,
		"-",
		targetVolumeName)

	rbdRecvCmd.Stdin, _ = rbdSendCmd.StdoutPipe()
	rbdRecvCmd.Stdout = os.Stdout
	rbdRecvCmd.Stderr = os.Stderr

	err := rbdRecvCmd.Start()
	if err != nil {
		return err
	}

	err = rbdSendCmd.Run()
	if err != nil {
		return err
	}

	err = rbdRecvCmd.Wait()
	if err != nil {
		return err
	}

	logger.Debugf(`Created non-sparse copy of RBD storage volume "%s" to "%s"`, sourceVolumeName, targetVolumeName)
	return nil
}
func (s *storageCeph) copyWithSnapshots(sourceVolumeName string,
	targetVolumeName string, sourceParentSnapshot string) error {
	logger.Debugf(`Creating non-sparse copy of RBD storage volume "%s to "%s"`, sourceVolumeName, targetVolumeName)

	args := []string{
		"export-diff",
		"--id", s.UserName,
		"--cluster", s.ClusterName,
		sourceVolumeName,
	}

	if sourceParentSnapshot != "" {
		args = append(args, "--from-snap", sourceParentSnapshot)
	}

	// redirect output to stdout
	args = append(args, "-")

	rbdSendCmd := exec.Command("rbd", args...)
	rbdRecvCmd := exec.Command(
		"rbd",
		"--id", s.UserName,
		"import-diff",
		"--cluster", s.ClusterName,
		"-",
		targetVolumeName)

	rbdRecvCmd.Stdin, _ = rbdSendCmd.StdoutPipe()
	rbdRecvCmd.Stdout = os.Stdout
	rbdRecvCmd.Stderr = os.Stderr

	err := rbdRecvCmd.Start()
	if err != nil {
		return err
	}

	err = rbdSendCmd.Run()
	if err != nil {
		return err
	}

	err = rbdRecvCmd.Wait()
	if err != nil {
		return err
	}

	logger.Debugf(`Created non-sparse copy of RBD storage volume "%s" to "%s"`, sourceVolumeName, targetVolumeName)
	return nil
}
// copyWithSnapshots creates a non-sparse copy of a container including its
// snapshots
// This does not introduce a dependency relation between the source RBD storage
// volume and the target RBD storage volume.