@@ -86,13 +86,13 @@ type snapshotAction struct {
86
86
kubeClient kubernetes.Clientset
87
87
namespace string
88
88
vgName string
89
+ lvType string
89
90
hostWritePath string
90
91
}
91
92
92
93
const (
93
- linearType = "linear"
94
94
stripedType = "striped"
95
- mirrorType = "mirror "
95
+ dmThinType = "dm-thin "
96
96
actionTypeCreate = "create"
97
97
actionTypeDelete = "delete"
98
98
actionTypeClone = "clone"
@@ -279,7 +279,7 @@ func createSnapshotterPod(ctx context.Context, sa snapshotAction) (err error) {
279
279
args := []string {}
280
280
switch sa .action {
281
281
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 )
283
283
case actionTypeDelete :
284
284
args = append (args , "deletesnap" , "--snapname" , sa .snapshotName , "--vgname" , sa .vgName )
285
285
default :
@@ -436,40 +436,51 @@ func CreateLVS(vg string, name string, size uint64, lvmType string) (string, err
436
436
return "" , fmt .Errorf ("size must be greater than 0" )
437
437
}
438
438
439
- if ! (lvmType == "linear" || lvmType == "mirror" || lvmType == "striped" ) {
440
- return "" , fmt .Errorf ("lvmType is incorrect: %s" , lvmType )
441
- }
442
-
443
439
// TODO: check available capacity, fail if request doesn't fit
444
440
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" }
446
461
447
462
pvs , err := pvCount (vg )
448
463
if err != nil {
449
464
return "" , fmt .Errorf ("unable to determine pv count of vg: %w" , err )
450
465
}
451
466
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." )
455
469
}
456
470
457
471
switch lvmType {
458
472
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 )
463
476
default :
464
477
return "" , fmt .Errorf ("unsupported lvmtype: %s" , lvmType )
465
478
}
466
479
467
- executor := cmd .NewExecutor ()
468
480
tags := []string {"harvester-csi-lvm" }
469
481
for _ , tag := range tags {
470
482
args = append (args , "--addtag" , tag )
471
483
}
472
- args = append (args , vg )
473
484
klog .Infof ("lvcreate %s" , args )
474
485
out , err := executor .Execute ("lvcreate" , args )
475
486
return out , err
@@ -535,7 +546,7 @@ func RemoveLVS(name string) (string, error) {
535
546
return out , err
536
547
}
537
548
538
- func CreateSnapshot (snapshotName , srcVolName , vgName string , volSize int64 ) (string , error ) {
549
+ func CreateSnapshot (snapshotName , srcVolName , vgName string , volSize int64 , lvType string ) (string , error ) {
539
550
if snapshotName == "" || srcVolName == "" {
540
551
return "" , fmt .Errorf ("invalid empty name or path" )
541
552
}
@@ -552,7 +563,16 @@ func CreateSnapshot(snapshotName, srcVolName, vgName string, volSize int64) (str
552
563
// Names starting "snapshot" are reserved for internal use by LVM
553
564
// we patch new snapName as "lvm-<snapshotName>"
554
565
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
+ }
556
576
args = append (args , fmt .Sprintf ("/dev/%s/%s" , vgName , srcVolName ))
557
577
klog .Infof ("lvcreate %s" , args )
558
578
out , err := executor .Execute ("lvcreate" , args )
@@ -593,6 +613,41 @@ func pvCount(vgname string) (int, error) {
593
613
return count , nil
594
614
}
595
615
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
+
596
651
func getRelatedVG (lvname string ) (string , error ) {
597
652
executor := cmd .NewExecutor ()
598
653
// we would like to get the lvname, vgname as below:
0 commit comments