Skip to content

Commit 1509a84

Browse files
committed
controller: support lvm type dm-thin
- also drop linear/mirror Signed-off-by: Vicente Cheng <vicente.cheng@suse.com>
1 parent 2dcadf1 commit 1509a84

File tree

3 files changed

+87
-21
lines changed

3 files changed

+87
-21
lines changed

cmd/provisioner/createsnap.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ func createSnapCmd() *cli.Command {
3030
Name: flagLVName,
3131
Usage: "Required. the name of the volumegroup",
3232
},
33+
&cli.StringFlag{
34+
Name: flagLVMType,
35+
Usage: "Required. the type of the source lvm",
36+
},
3337
},
3438
Action: func(c *cli.Context) error {
3539
if err := createSnap(c); err != nil {
@@ -58,6 +62,10 @@ func createSnap(c *cli.Context) error {
5862
if snapName == "" {
5963
return fmt.Errorf("invalid empty flag %v", flagLVMType)
6064
}
65+
lvType := c.String(flagLVMType)
66+
if lvType == "" {
67+
return fmt.Errorf("invalid empty flag %v", flagLVMType)
68+
}
6169

6270
klog.Infof("create snapshot: %s source size: %d source lv: %s/%s", snapName, lvSize, vgName, lvName)
6371

@@ -69,7 +77,7 @@ func createSnap(c *cli.Context) error {
6977
}
7078
}
7179

72-
output, err := lvm.CreateSnapshot(snapName, lvName, vgName, lvSize)
80+
output, err := lvm.CreateSnapshot(snapName, lvName, vgName, lvSize, lvType)
7381
if err != nil {
7482
return fmt.Errorf("unable to create Snapshot: %w output:%s", err, output)
7583
}

pkg/lvm/controllerserver.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
116116
}
117117

118118
lvmType := req.GetParameters()["type"]
119-
if !(lvmType == "linear" || lvmType == "mirror" || lvmType == "striped") {
119+
if !(lvmType == "striped" || lvmType == "dm-thin") {
120120
return nil, status.Errorf(codes.Internal, "lvmType is incorrect: %s", lvmType)
121121
}
122122

@@ -430,6 +430,7 @@ func (cs *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
430430
ns := volume.Spec.NodeAffinity.Required.NodeSelectorTerms
431431
node := ns[0].MatchExpressions[0].Values[0]
432432
vgName := volume.Spec.CSI.VolumeAttributes["vgName"]
433+
lvType := volume.Spec.CSI.VolumeAttributes["type"]
433434
//snapSize := strconv.FormatUint(volume.Spec.CSI.VolumeAttributes["RequiredBytes"], 10)
434435
snapSizeStr := volume.Spec.CSI.VolumeAttributes["RequiredBytes"]
435436
snapSize, err := strconv.ParseInt(snapSizeStr, 10, 64)
@@ -449,6 +450,7 @@ func (cs *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
449450
nodeName: node,
450451
snapSize: snapSize,
451452
vgName: vgName,
453+
lvType: lvType,
452454
hostWritePath: cs.hostWritePath,
453455
kubeClient: cs.kubeClient,
454456
namespace: cs.namespace,
@@ -503,6 +505,7 @@ func (cs *controllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteS
503505
snapshotName: snapName,
504506
nodeName: node,
505507
vgName: vgName,
508+
lvType: "", // not used
506509
hostWritePath: cs.hostWritePath,
507510
kubeClient: cs.kubeClient,
508511
namespace: cs.namespace,

pkg/lvm/lvm.go

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,13 @@ type snapshotAction struct {
8686
kubeClient kubernetes.Clientset
8787
namespace string
8888
vgName string
89+
lvType string
8990
hostWritePath string
9091
}
9192

9293
const (
93-
linearType = "linear"
9494
stripedType = "striped"
95-
mirrorType = "mirror"
95+
dmThinType = "dm-thin"
9696
actionTypeCreate = "create"
9797
actionTypeDelete = "delete"
9898
actionTypeClone = "clone"
@@ -279,7 +279,7 @@ func createSnapshotterPod(ctx context.Context, sa snapshotAction) (err error) {
279279
args := []string{}
280280
switch sa.action {
281281
case actionTypeCreate:
282-
args = append(args, "createsnap", "--snapname", sa.snapshotName, "--lvname", sa.srcVolName, "--vgname", sa.vgName, "--lvsize", fmt.Sprintf("%d", sa.snapSize))
282+
args = append(args, "createsnap", "--snapname", sa.snapshotName, "--lvname", sa.srcVolName, "--vgname", sa.vgName, "--lvsize", fmt.Sprintf("%d", sa.snapSize), "--lvmtype", sa.lvType)
283283
case actionTypeDelete:
284284
args = append(args, "deletesnap", "--snapname", sa.snapshotName, "--vgname", sa.vgName)
285285
default:
@@ -436,40 +436,51 @@ func CreateLVS(vg string, name string, size uint64, lvmType string) (string, err
436436
return "", fmt.Errorf("size must be greater than 0")
437437
}
438438

439-
if !(lvmType == "linear" || lvmType == "mirror" || lvmType == "striped") {
440-
return "", fmt.Errorf("lvmType is incorrect: %s", lvmType)
441-
}
442-
443439
// TODO: check available capacity, fail if request doesn't fit
444440

445-
args := []string{"-v", "--yes", "-n", name, "-W", "y", "-L", fmt.Sprintf("%db", size)}
441+
executor := cmd.NewExecutor()
442+
thinPoolName := ""
443+
// we need to create thin pool first if the lvmType is dm-thin
444+
if lvmType == dmThinType {
445+
thinPoolName = fmt.Sprintf("%s-thinpool", vg)
446+
found, err := getThinPool(vg, thinPoolName)
447+
if err != nil {
448+
return "", fmt.Errorf("unable to determine if thinpool exists: %w", err)
449+
}
450+
if !found {
451+
args := []string{"-l90%FREE", "--thinpool", thinPoolName, vg}
452+
klog.Infof("lvcreate %s", args)
453+
_, err := executor.Execute("lvcreate", args)
454+
if err != nil {
455+
return "", fmt.Errorf("unable to create thinpool: %w", err)
456+
}
457+
}
458+
}
459+
460+
args := []string{"-v", "--yes", "-n", name, "-W", "y"}
446461

447462
pvs, err := pvCount(vg)
448463
if err != nil {
449464
return "", fmt.Errorf("unable to determine pv count of vg: %w", err)
450465
}
451466

452-
if pvs < 2 {
453-
klog.Warning("pvcount is <2 only linear is supported")
454-
lvmType = linearType
467+
if pvs < 2 && lvmType == stripedType {
468+
klog.Warning("pvcount is <2, the striped does not meaningful.")
455469
}
456470

457471
switch lvmType {
458472
case stripedType:
459-
args = append(args, "--type", "striped", "--stripes", fmt.Sprintf("%d", pvs))
460-
case mirrorType:
461-
args = append(args, "--type", "raid1", "--mirrors", "1", "--nosync")
462-
case linearType:
473+
args = append(args, "-L", fmt.Sprintf("%db", size), "--type", "striped", "--stripes", fmt.Sprintf("%d", pvs), vg)
474+
case dmThinType:
475+
args = append(args, "-V", fmt.Sprintf("%db", size), "--thin-pool", thinPoolName, vg)
463476
default:
464477
return "", fmt.Errorf("unsupported lvmtype: %s", lvmType)
465478
}
466479

467-
executor := cmd.NewExecutor()
468480
tags := []string{"harvester-csi-lvm"}
469481
for _, tag := range tags {
470482
args = append(args, "--addtag", tag)
471483
}
472-
args = append(args, vg)
473484
klog.Infof("lvcreate %s", args)
474485
out, err := executor.Execute("lvcreate", args)
475486
return out, err
@@ -535,7 +546,7 @@ func RemoveLVS(name string) (string, error) {
535546
return out, err
536547
}
537548

538-
func CreateSnapshot(snapshotName, srcVolName, vgName string, volSize int64) (string, error) {
549+
func CreateSnapshot(snapshotName, srcVolName, vgName string, volSize int64, lvType string) (string, error) {
539550
if snapshotName == "" || srcVolName == "" {
540551
return "", fmt.Errorf("invalid empty name or path")
541552
}
@@ -552,7 +563,16 @@ func CreateSnapshot(snapshotName, srcVolName, vgName string, volSize int64) (str
552563
// Names starting "snapshot" are reserved for internal use by LVM
553564
// we patch new snapName as "lvm-<snapshotName>"
554565
snapshotName = fmt.Sprintf("lvm-%s", snapshotName)
555-
args := []string{"-s", "-y", "-n", snapshotName, "-L", fmt.Sprintf("%db", volSize)}
566+
args := []string{"-s", "-y", "-n", snapshotName}
567+
switch lvType {
568+
case stripedType:
569+
args = append(args, "-L", fmt.Sprintf("%db", volSize))
570+
case dmThinType:
571+
// no-size option for the dm-thin
572+
break
573+
default:
574+
return "", fmt.Errorf("unsupported lvmtype: %s", lvType)
575+
}
556576
args = append(args, fmt.Sprintf("/dev/%s/%s", vgName, srcVolName))
557577
klog.Infof("lvcreate %s", args)
558578
out, err := executor.Execute("lvcreate", args)
@@ -593,6 +613,41 @@ func pvCount(vgname string) (int, error) {
593613
return count, nil
594614
}
595615

616+
func getThinPool(vgName, thinpoolName string) (bool, error) {
617+
executor := cmd.NewExecutor()
618+
// we would like to get the segtype, name as below:
619+
// thin thinvol01 <-- this is volume
620+
// thin-pool vg02-thinpool <-- this is thin-pool
621+
args := []string{"--noheadings", "-o", "segtype,name", vgName}
622+
out, err := executor.Execute("lvs", args)
623+
if err != nil {
624+
klog.Infof("execute lvs %s, err: %v", args, err)
625+
return false, err
626+
}
627+
lines := strings.Split(out, "\n")
628+
// type[Name]
629+
// type: thin -> vol name
630+
// thin-pool -> pool name
631+
thinInfo := make(map[string]string)
632+
for _, line := range lines {
633+
if line == "" {
634+
continue
635+
}
636+
parts := strings.Fields(line)
637+
if len(parts) != 2 {
638+
klog.Warningf("unexpected output from lvs: %s", line)
639+
continue
640+
}
641+
thinInfo[parts[0]] = parts[1]
642+
}
643+
for typeName, val := range thinInfo {
644+
if typeName == "thin-pool" && val == thinpoolName {
645+
return true, nil
646+
}
647+
}
648+
return false, nil
649+
}
650+
596651
func getRelatedVG(lvname string) (string, error) {
597652
executor := cmd.NewExecutor()
598653
// we would like to get the lvname, vgname as below:

0 commit comments

Comments
 (0)