func CloneLV(ctx context.Context, src, dest string) (string, error) {
	sp, _ := opentracing.StartSpanFromContext(ctx, "sys.dd")
	sp.SetTag("component", "dd")
	sp.SetTag("span.kind", "client")
	defer sp.Finish()
	cmd := exec.Command("dd", fmt.Sprintf("if=%s", src), fmt.Sprintf("of=%s", dest), "bs=4M")
	out, err := cmd.CombinedOutput()
	return string(out), err
}
CloneLV clones a volume via dd
package commands
import (
	"errors"
	"fmt"
	"os/exec"
	"strings"
	"github.com/opentracing/opentracing-go"
	"golang.org/x/net/context"
	"github.com/google/lvmd/parser"
)
func ListLV(ctx context.Context, listspec string) ([]*parser.LV, error) {
	sp, _ := opentracing.StartSpanFromContext(ctx, "lvm.lvs")
	sp.SetTag("component", "lvm")
	sp.SetTag("span.kind", "client")
	defer sp.Finish()
	cmd := exec.Command("lvs", "--units=b", "--separator=<:SEP:>", "--nosuffix", "--noheadings",
		"-o", "lv_name,lv_size,lv_uuid,lv_attr,copy_percent,lv_kernel_major,lv_kernel_minor,lv_tags,vg_name", "--nameprefixes", "-a", listspec)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, err
	}
	outStr := strings.TrimSpace(string(out))
	outLines := strings.Split(outStr, "\n")
	lvs := make([]*parser.LV, len(outLines))
	for i, line := range outLines {
		line = strings.TrimSpace(line)
		lv, err := parser.ParseLV(line)
		if err != nil {
			return nil, err
		}
		lvs[i] = lv
	}
	return lvs, nil
}
func CreateLV(ctx context.Context, vg string, name string, size uint64, mirrors uint32, tags []string) (string, error) {
	if size == 0 {
		return "", errors.New("size must be greater than 0")
	}
	sp, _ := opentracing.StartSpanFromContext(ctx, "lvm.lvcreate")
	sp.SetTag("component", "lvm")
	sp.SetTag("span.kind", "client")
	defer sp.Finish()
	args := []string{"-v", "-n", name, "-L", fmt.Sprintf("%db", size)}
	if mirrors > 0 {
		args = append(args, "-m", fmt.Sprintf("%d", mirrors), "--nosync")
	}
	for _, tag := range tags {
		args = append(args, "--add-tag", tag)
	}
	args = append(args, vg)
	cmd := exec.Command("lvcreate", args...)
	out, err := cmd.CombinedOutput()
	return string(out), err
}
const ProtectedTagName = "protected"
func RemoveLV(ctx context.Context, vg string, name string) (string, error) {
	lvs, err := ListLV(ctx, fmt.Sprintf("%s/%s", vg, name))
	if err != nil {
		return "", fmt.Errorf("failed to list LVs: %v", err)
	}
	if len(lvs) != 1 {
		return "", fmt.Errorf("expected 1 LV, got %d", len(lvs))
	}
	for _, tag := range lvs[0].Tags {
		if tag == ProtectedTagName {
			return "", errors.New("volume is protected")
		}
	}
	sp, _ := opentracing.StartSpanFromContext(ctx, "lvm.lvremove")
	sp.SetTag("component", "lvm")
	sp.SetTag("span.kind", "client")
	defer sp.Finish()
	cmd := exec.Command("lvremove", "-v", "-f", fmt.Sprintf("%s/%s", vg, name))
	out, err := cmd.CombinedOutput()
	return string(out), err
}