Skip to content

Commit b521cee

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

File tree

6 files changed

+249
-55
lines changed

6 files changed

+249
-55
lines changed

cmd/provisioner/clonelv.go

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"fmt"
55
"os"
6+
"strings"
67
"syscall"
78
"time"
89

@@ -17,8 +18,16 @@ func cloneLVCmd() *cli.Command {
1718
Name: "clonelv",
1819
Flags: []cli.Flag{
1920
&cli.StringFlag{
20-
Name: flagSrcDev,
21-
Usage: "Required. Source device name.",
21+
Name: flagSrcLVName,
22+
Usage: "Required. Source LV name.",
23+
},
24+
&cli.StringFlag{
25+
Name: flagSrcVGName,
26+
Usage: "Required. Source VG name",
27+
},
28+
&cli.StringFlag{
29+
Name: flagSrcType,
30+
Usage: "Required. Source type, can be either striped or dm-thin",
2231
},
2332
&cli.StringFlag{
2433
Name: flagLVName,
@@ -48,9 +57,17 @@ func cloneLVCmd() *cli.Command {
4857
}
4958

5059
func clonelv(c *cli.Context) error {
51-
srcDev := c.String(flagSrcDev)
52-
if srcDev == "" {
53-
return fmt.Errorf("invalid empty flag %v", flagSrcDev)
60+
srcLvName := c.String(flagSrcLVName)
61+
if srcLvName == "" {
62+
return fmt.Errorf("invalid empty flag %v", flagSrcLVName)
63+
}
64+
srcVgName := c.String(flagSrcVGName)
65+
if srcVgName == "" {
66+
return fmt.Errorf("invalid empty flag %v", flagSrcVGName)
67+
}
68+
srcType := c.String(flagSrcType)
69+
if srcType == "" {
70+
return fmt.Errorf("invalid empty flag %v", flagSrcType)
5471
}
5572
dstLV := c.String(flagLVName)
5673
if dstLV == "" {
@@ -69,14 +86,7 @@ func clonelv(c *cli.Context) error {
6986
return fmt.Errorf("invalid empty flag %v", flagLVSize)
7087
}
7188

72-
klog.Infof("Clone from src:%s, to dst: %s/%s", srcDev, dstVGName, dstLV)
73-
74-
// check source dev
75-
src, err := os.OpenFile(srcDev, syscall.O_RDONLY|syscall.O_DIRECT, 0)
76-
if err != nil {
77-
return fmt.Errorf("unable to open source device: %w", err)
78-
}
79-
defer src.Close()
89+
klog.Infof("Clone from src: %s, to dst: %s/%s", srcLvName, dstVGName, dstLV)
8090

8191
if !lvm.VgExists(dstVGName) {
8292
lvm.VgActivate()
@@ -86,6 +96,25 @@ func clonelv(c *cli.Context) error {
8696
}
8797
}
8898

99+
klog.Infof("clone lv %s, vg: %s, type: %s", srcLvName, srcVgName, srcType)
100+
if strings.HasPrefix(srcLvName, snapshotPrefix) && srcType == lvm.DmThinType && srcType == dstLVType && srcVgName == dstVGName {
101+
// special case for clone dm-thin, so activate the target
102+
_, err := lvm.CreateSnapshot(dstLV, srcLvName, srcVgName, int64(dstSize), dstLVType, createSnapshotForClone)
103+
if err != nil {
104+
return fmt.Errorf("unable to create snapshot: %w", err)
105+
}
106+
klog.Infof("lv: %s/%s cloned from %s", dstVGName, dstLV, srcLvName)
107+
return nil
108+
}
109+
110+
// check source dev
111+
srcDev := fmt.Sprintf("/dev/%s/%s", srcVgName, srcLvName)
112+
src, err := os.OpenFile(srcDev, syscall.O_RDONLY|syscall.O_DIRECT, 0)
113+
if err != nil {
114+
return fmt.Errorf("unable to open source device: %w", err)
115+
}
116+
defer src.Close()
117+
89118
output, err := lvm.CreateLVS(dstVGName, dstLV, dstSize, dstLVType)
90119
if err != nil {
91120
return fmt.Errorf("unable to create lv: %w output:%s", err, output)

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, !createSnapshotForClone)
7381
if err != nil {
7482
return fmt.Errorf("unable to create Snapshot: %w output:%s", err, output)
7583
}

cmd/provisioner/deletelv.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ func deleteLVCmd() *cli.Command {
1717
Name: flagLVName,
1818
Usage: "Required. Specify lv name.",
1919
},
20+
&cli.StringFlag{
21+
Name: flagSrcVGName,
22+
Usage: "Required. Source VG name",
23+
},
24+
&cli.StringFlag{
25+
Name: flagSrcType,
26+
Usage: "Required. Source type, can be either striped or dm-thin",
27+
},
2028
},
2129
Action: func(c *cli.Context) error {
2230
if err := deleteLV(c); err != nil {
@@ -33,13 +41,27 @@ func deleteLV(c *cli.Context) error {
3341
if lvName == "" {
3442
return fmt.Errorf("invalid empty flag %v", flagLVName)
3543
}
44+
vgName := c.String(flagSrcVGName)
45+
if vgName == "" {
46+
return fmt.Errorf("invalid empty flag %v", flagSrcVGName)
47+
}
48+
vgType := c.String(flagSrcType)
49+
if vgType == "" {
50+
return fmt.Errorf("invalid empty flag %v", flagSrcType)
51+
}
3652

3753
klog.Infof("delete lv %s", lvName)
3854

3955
output, err := lvm.RemoveLVS(lvName)
4056
if err != nil {
4157
return fmt.Errorf("unable to delete lv: %w output:%s", err, output)
4258
}
59+
if vgType == lvm.DmThinType {
60+
err := lvm.RemoveThinPool(vgName)
61+
if err != nil {
62+
return fmt.Errorf("unable to delete thinpool: %w output:%s", err, output)
63+
}
64+
}
4365
klog.Infof("lv %s is deleted", lvName)
4466
return nil
4567
}

cmd/provisioner/main.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ import (
99
)
1010

1111
const (
12-
flagLVName = "lvname"
13-
flagLVSize = "lvsize"
14-
flagVGName = "vgname"
15-
flagDevicesPattern = "devices"
16-
flagLVMType = "lvmtype"
17-
flagSnapName = "snapname"
18-
flagSrcDev = "srcdev"
12+
flagLVName = "lvname"
13+
flagLVSize = "lvsize"
14+
flagVGName = "vgname"
15+
flagDevicesPattern = "devices"
16+
flagLVMType = "lvmtype"
17+
flagSnapName = "snapname"
18+
flagSrcLVName = "srclvname"
19+
flagSrcVGName = "srcvgname"
20+
flagSrcType = "srctype"
21+
createSnapshotForClone = true
22+
snapshotPrefix = "lvm-snapshot-"
1923
)
2024

2125
func cmdNotFound(c *cli.Context, command string) {

pkg/lvm/controllerserver.go

Lines changed: 33 additions & 8 deletions
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

@@ -205,11 +205,17 @@ func (cs *controllerServer) cloneFromSnapshot(ctx context.Context, snapContent *
205205
ns := srcVol.Spec.NodeAffinity.Required.NodeSelectorTerms
206206
srcNode := ns[0].MatchExpressions[0].Values[0]
207207
srcVgName := srcVol.Spec.CSI.VolumeAttributes["vgName"]
208+
srcVgType := srcVol.Spec.CSI.VolumeAttributes["type"]
208209
restoreSize := *snapContent.Status.RestoreSize
209210

210211
snapshotLVName := fmt.Sprintf("lvm-%s", *snapContent.Status.SnapshotHandle)
211-
srcSnapDev := fmt.Sprintf("/dev/%s/%s", srcVgName, snapshotLVName)
212-
klog.V(4).Infof("cloning volume from %s ", srcSnapDev)
212+
//srcSnapDev := fmt.Sprintf("/dev/%s/%s", srcVgName, snapshotLVName)
213+
srcInfo := &srcInfo{
214+
srcLVName: snapshotLVName,
215+
srcVGName: srcVgName,
216+
srcType: srcVgType,
217+
}
218+
klog.V(4).Infof("cloning volume from %s/%s ", srcVgName, snapshotLVName)
213219

214220
if restoreSize > dstSize {
215221
return status.Error(codes.InvalidArgument, "source volume size is larger than destination volume size")
@@ -230,7 +236,7 @@ func (cs *controllerServer) cloneFromSnapshot(ctx context.Context, snapContent *
230236
namespace: cs.namespace,
231237
vgName: dstVGName,
232238
hostWritePath: cs.hostWritePath,
233-
srcDev: srcSnapDev,
239+
srcInfo: srcInfo,
234240
}
235241
if err := createProvisionerPod(ctx, va); err != nil {
236242
klog.Errorf("error creating provisioner pod :%v", err)
@@ -244,14 +250,22 @@ func (cs *controllerServer) cloneFromVolume(ctx context.Context, srcVol *v1.Pers
244250
ns := srcVol.Spec.NodeAffinity.Required.NodeSelectorTerms
245251
srcNode := ns[0].MatchExpressions[0].Values[0]
246252
srcVgName := srcVol.Spec.CSI.VolumeAttributes["vgName"]
253+
srcType := srcVol.Spec.CSI.VolumeAttributes["type"]
247254
srcSizeStr := srcVol.Spec.CSI.VolumeAttributes["RequiredBytes"]
248255
srcSize, err := strconv.ParseInt(srcSizeStr, 10, 64)
249256
if err != nil {
250257
klog.Errorf("error parsing srcSize: %v", err)
251258
return err
252259
}
253-
srcDev := fmt.Sprintf("/dev/%s/%s", srcVgName, srcVol.GetName())
254-
klog.V(4).Infof("cloning volume from %s ", srcDev)
260+
261+
//srcDev := fmt.Sprintf("/dev/%s/%s", srcVgName, srcVol.GetName())
262+
srcLVName := srcVol.GetName()
263+
srcInfo := &srcInfo{
264+
srcLVName: srcLVName,
265+
srcVGName: srcVgName,
266+
srcType: srcType,
267+
}
268+
klog.V(4).Infof("cloning volume from %s/%s ", srcVgName, srcLVName)
255269

256270
if srcSize > dstSize {
257271
return status.Error(codes.InvalidArgument, "source volume size is larger than destination volume size")
@@ -272,7 +286,7 @@ func (cs *controllerServer) cloneFromVolume(ctx context.Context, srcVol *v1.Pers
272286
namespace: cs.namespace,
273287
vgName: dstVGName,
274288
hostWritePath: cs.hostWritePath,
275-
srcDev: srcDev,
289+
srcInfo: srcInfo,
276290
}
277291
if err := createProvisionerPod(ctx, va); err != nil {
278292
klog.Errorf("error creating provisioner pod :%v", err)
@@ -302,6 +316,13 @@ func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
302316
klog.V(4).Infof("volume %s to be deleted", volume)
303317
ns := volume.Spec.NodeAffinity.Required.NodeSelectorTerms
304318
node := ns[0].MatchExpressions[0].Values[0]
319+
srcVgName := volume.Spec.CSI.VolumeAttributes["vgName"]
320+
srcType := volume.Spec.CSI.VolumeAttributes["type"]
321+
srcInfo := &srcInfo{
322+
srcLVName: volID,
323+
srcVGName: srcVgName,
324+
srcType: srcType,
325+
}
305326

306327
klog.V(4).Infof("from node %s ", node)
307328

@@ -318,13 +339,14 @@ func (cs *controllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
318339

319340
va := volumeAction{
320341
action: actionTypeDelete,
321-
name: req.GetVolumeId(),
342+
name: volID,
322343
nodeName: node,
323344
pullPolicy: cs.pullPolicy,
324345
provisionerImage: cs.provisionerImage,
325346
kubeClient: cs.kubeClient,
326347
namespace: cs.namespace,
327348
hostWritePath: cs.hostWritePath,
349+
srcInfo: srcInfo,
328350
}
329351
if err := createProvisionerPod(ctx, va); err != nil {
330352
klog.Errorf("error creating provisioner pod :%v", err)
@@ -430,6 +452,7 @@ func (cs *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
430452
ns := volume.Spec.NodeAffinity.Required.NodeSelectorTerms
431453
node := ns[0].MatchExpressions[0].Values[0]
432454
vgName := volume.Spec.CSI.VolumeAttributes["vgName"]
455+
lvType := volume.Spec.CSI.VolumeAttributes["type"]
433456
snapSizeStr := volume.Spec.CSI.VolumeAttributes["RequiredBytes"]
434457
snapSize, err := strconv.ParseInt(snapSizeStr, 10, 64)
435458
if err != nil {
@@ -448,6 +471,7 @@ func (cs *controllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateS
448471
nodeName: node,
449472
snapSize: snapSize,
450473
vgName: vgName,
474+
lvType: lvType,
451475
hostWritePath: cs.hostWritePath,
452476
kubeClient: cs.kubeClient,
453477
namespace: cs.namespace,
@@ -502,6 +526,7 @@ func (cs *controllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteS
502526
snapshotName: snapName,
503527
nodeName: node,
504528
vgName: vgName,
529+
lvType: "", // not used
505530
hostWritePath: cs.hostWritePath,
506531
kubeClient: cs.kubeClient,
507532
namespace: cs.namespace,

0 commit comments

Comments
 (0)