Skip to content

Commit 8b8efb7

Browse files
committed
✨ Extra format options (mkfs) added
Signed-off-by: Muhammed Hussein Karimi <[email protected]>
1 parent 0872362 commit 8b8efb7

File tree

10 files changed

+187
-6
lines changed

10 files changed

+187
-6
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
extra format options (mkfs) added
2+
3+
used to add extra options to mkfs while formatting volumes with filesystem

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ require (
5353
github.com/mailru/easyjson v0.7.7 // indirect
5454
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
5555
github.com/moby/spdystream v0.2.0 // indirect
56+
github.com/moby/sys/mountinfo v0.6.2 // indirect
5657
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
5758
github.com/modern-go/reflect2 v1.0.2 // indirect
5859
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -77,6 +78,7 @@ require (
7778
k8s.io/apiextensions-apiserver v0.27.2 // indirect
7879
k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4 // indirect
7980
k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect
81+
k8s.io/mount-utils v0.26.15 // indirect
8082
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
8183
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
8284
sigs.k8s.io/testing_frameworks v0.1.2 // indirect

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
107107
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
108108
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
109109
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
110+
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
110111
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
111112
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
112113
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
@@ -226,6 +227,7 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P
226227
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
227228
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
228229
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
230+
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
229231
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
230232
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
231233
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -234,6 +236,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
234236
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
235237
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
236238
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
239+
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
237240
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
238241
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
239242
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@@ -261,6 +264,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr
261264
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
262265
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
263266
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
267+
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
268+
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
264269
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
265270
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
266271
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
@@ -273,6 +278,7 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
273278
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
274279
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
275280
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
281+
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
276282
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
277283
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
278284
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
@@ -830,6 +836,8 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H
830836
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
831837
k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI=
832838
k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515/go.mod h1:kzo02I3kQ4BTtEfVLaPbjvCkX97YqGve33wzlb3fofQ=
839+
k8s.io/mount-utils v0.26.15 h1:TvTNwRNiXRlxjb7ZUlKObpfINRmcFqMF2i+rb3iJ/co=
840+
k8s.io/mount-utils v0.26.15/go.mod h1:huSg2NI5P8ZNfE8PkQmm5a9fFZ9iHCXFxP/rasMCgYA=
833841
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
834842
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
835843
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=

pkg/driver/agent.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,11 @@ func GetVolAndMountInfo(
215215
if err != nil {
216216
return nil, nil, err
217217
}
218+
mountinfo.FormatOptions = nil
219+
formatOptions := strings.TrimSpace(req.VolumeContext[lvm.FormatOptionsKey])
220+
if len(formatOptions) > 0 {
221+
mountinfo.FormatOptions = strings.Split(formatOptions, " ")
222+
}
218223

219224
return vol, &mountinfo, nil
220225
}

pkg/driver/controller.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,11 @@ func (cs *controller) CreateVolume(
362362
analytics.VolumeProvision)
363363

364364
topology := map[string]string{lvm.LVMTopologyKey: vol.Spec.OwnerNodeID}
365-
cntx := map[string]string{lvm.VolGroupKey: vol.Spec.VolGroup, lvm.OpenEBSCasTypeKey: lvm.LVMCasTypeName}
365+
cntx := map[string]string{
366+
lvm.VolGroupKey: vol.Spec.VolGroup,
367+
lvm.OpenEBSCasTypeKey: lvm.LVMCasTypeName,
368+
lvm.FormatOptionsKey: params.FormatOptions,
369+
}
366370

367371
return csipayload.NewCreateVolumeResponseBuilder().
368372
WithName(volName).

pkg/driver/params.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ type VolumeParams struct {
3939
// extra optional metadata passed by external provisioner
4040
// if enabled. See --extra-create-metadata flag for more details.
4141
// https://github.com/kubernetes-csi/external-provisioner#recommended-optional-arguments
42-
PVCName string
43-
PVCNamespace string
44-
PVName string
42+
PVCName string
43+
PVCNamespace string
44+
PVName string
45+
FormatOptions string
4546
}
4647

4748
// SnapshotParams holds collection of supported settings that can
@@ -73,6 +74,8 @@ func NewVolumeParams(m map[string]string) (*VolumeParams, error) {
7374
vgPattern = fmt.Sprintf("^%v$", volGroup)
7475
}
7576

77+
params.FormatOptions = m["formatoptions"]
78+
7679
var err error
7780
if params.VgPattern, err = regexp.Compile(vgPattern); err != nil {
7881
return nil, fmt.Errorf("invalid volgroup/vgpattern param %v: %v", vgPattern, err)

pkg/lvm/mount.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import (
2828
"google.golang.org/grpc/codes"
2929
"google.golang.org/grpc/status"
3030
"k8s.io/klog/v2"
31+
"k8s.io/mount-utils"
3132
utilexec "k8s.io/utils/exec"
32-
"k8s.io/utils/mount"
3333

3434
apis "github.com/openebs/lvm-localpv/pkg/apis/openebs.io/lvm/v1alpha1"
3535
)
@@ -53,6 +53,10 @@ type MountInfo struct {
5353
// MountOptions specifies the options with
5454
// which mount needs to be attempted
5555
MountOptions []string `json:"mountOptions"`
56+
57+
// FormatOptions specifies the options that
58+
// will be added to newly created volume on first use
59+
FormatOptions []string `json:"formatOptions"`
5660
}
5761

5862
// PodLVInfo contains the pod, LVGroup related info
@@ -68,7 +72,14 @@ type PodLVInfo struct {
6872
func FormatAndMountVol(devicePath string, mountInfo *MountInfo) error {
6973
mounter := &mount.SafeFormatAndMount{Interface: mount.New(""), Exec: utilexec.New()}
7074

71-
err := mounter.FormatAndMount(devicePath, mountInfo.MountPath, mountInfo.FSType, mountInfo.MountOptions)
75+
err := mounter.FormatAndMountSensitiveWithFormatOptions(
76+
devicePath,
77+
mountInfo.MountPath,
78+
mountInfo.FSType,
79+
mountInfo.MountOptions,
80+
nil, // sensitiveOptions
81+
mountInfo.FormatOptions,
82+
)
7283
if err != nil {
7384
klog.Errorf(
7485
"lvm: failed to mount volume %s [%s] to %s, error %v",

pkg/lvm/volume.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ const (
5858
OpenEBSCasTypeKey string = "openebs.io/cas-type"
5959
// LVMCasTypeName for the name of the cas-type
6060
LVMCasTypeName string = "localpv-lvm"
61+
// FormatOptionsKey for Extra Format Options in storage class
62+
FormatOptionsKey string = "openebs.io/format-options"
6163
)
6264

6365
var (

tests/provision_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,22 @@ func fsVolCreationTest() {
8686
}
8787
}
8888

89+
func formatOptionsTest() {
90+
formatOptions := "-b 4096 -N 5000000"
91+
By("####### Creating the storage class with formatOptions : " + formatOptions + " #######")
92+
createFormatOptionsStorageClass(formatOptions)
93+
By("Creating and verifying PVC bound status")
94+
createAndVerifyPVC(true)
95+
By("Creating and deploying app pod", createDeployVerifyFormatOptions)
96+
By("Verifying LVMVolume object to be Ready")
97+
VerifyLVMVolume(true, "")
98+
By("Deleting verifier pvc/pod")
99+
deleteAppAndPvc([]string{"format-options-verifier"}, pvcName)
100+
By("Verifying that PV is deleted after deletion")
101+
verifyPVForPVC(false, pvcName)
102+
By("Deleting storage class", deleteStorageClass)
103+
}
104+
89105
func blockVolCreationTest() {
90106
By("Creating default storage class", createStorageClass)
91107
By("Creating and verifying PVC bound status")
@@ -321,6 +337,7 @@ func volumeCreationTest() {
321337
device := setupVg(40, "lvmvg")
322338
defer cleanupVg(device, "lvmvg")
323339
By("###Running filesystem volume creation test###", fsVolCreationTest)
340+
By("###Running filesystem with formatOptions creation test###", formatOptionsTest)
324341
By("###Running block volume creation test###", blockVolCreationTest)
325342
By("###Running thin volume creation test###", thinVolCreationTest)
326343
By("###Running leak protection test###", leakProtectionTest)

tests/utils.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,29 @@ func createThinStorageClass() {
233233
gomega.Expect(err).To(gomega.BeNil(), "while creating a thinProvision storageclass {%s}", scName)
234234
}
235235

236+
func createFormatOptionsStorageClass(formatOptions string) {
237+
var (
238+
err error
239+
)
240+
241+
parameters := map[string]string{
242+
"volgroup": VOLGROUP,
243+
"formatOptions": formatOptions,
244+
}
245+
246+
ginkgo.By("building a default storage class")
247+
scObj, err = sc.NewBuilder().
248+
WithGenerateName(scName).
249+
WithVolumeExpansion(true).
250+
WithParametersNew(parameters).
251+
WithProvisioner(LocalProvisioner).Build()
252+
gomega.Expect(err).ShouldNot(gomega.HaveOccurred(),
253+
"while building formatOptions storageclass obj with prefix {%s}", scName)
254+
255+
scObj, err = SCClient.Create(scObj)
256+
gomega.Expect(err).To(gomega.BeNil(), "while creating a storageclass with formatOptions {%s}", scName)
257+
}
258+
236259
// VerifyLVMVolume verify the properties of a lvm-volume
237260
// expected_vg is supposed to be passed only when vgpatten was used for scheduling.
238261
// If its volgroup in sc then we can just match volgroup with lvmvolume's vg field.
@@ -560,6 +583,109 @@ func createAndDeployBlockAppPod() {
560583
}
561584
}
562585

586+
func createDeployVerifyFormatOptions() {
587+
ginkgo.By("creating and deploying verifier pod")
588+
createAndDeployVerifyFormatOptions()
589+
ginkgo.By("verifying verifier pod is running", verifyFormatOptionsVerifierPodRunning)
590+
}
591+
592+
func createAndDeployVerifyFormatOptions() {
593+
var err error
594+
appname := "format-options-verifier"
595+
labels := map[string]string{
596+
"role": "test",
597+
"app": appname,
598+
}
599+
ginkgo.By("building app " + appname + " using above lvm volume")
600+
deployObj, err = deploy.NewBuilder().
601+
WithName(appname).
602+
WithNamespace(OpenEBSNamespace).
603+
WithLabelsNew(labels).
604+
WithSelectorMatchLabelsNew(labels).
605+
WithPodTemplateSpecBuilder(
606+
pts.NewBuilder().
607+
WithLabelsNew(labels).
608+
WithContainerBuilders(
609+
container.NewBuilder().
610+
WithImage("debian:stable-slim").
611+
WithName("verifier").
612+
WithImagePullPolicy(corev1.PullIfNotPresent).
613+
WithEnvsNew(
614+
[]corev1.EnvVar{
615+
{
616+
Name: "MIN_INODES",
617+
Value: "5000000",
618+
},
619+
},
620+
).
621+
WithCommandNew(
622+
[]string{
623+
"bash",
624+
"-c",
625+
`test "$(df -i '/mnt/datadir' | tail -n 1 | awk '{print $2}')" -ge "$MIN_INODES" && tail -f /dev/null`,
626+
},
627+
).
628+
WithLifeCycle(
629+
&corev1.Lifecycle{
630+
PreStop: &corev1.LifecycleHandler{
631+
Exec: &corev1.ExecAction{
632+
Command: []string{
633+
"bash",
634+
"-c",
635+
"kill -9 $(pidof tail)",
636+
},
637+
},
638+
},
639+
},
640+
).
641+
WithVolumeMountsNew(
642+
[]corev1.VolumeMount{
643+
{
644+
Name: "datavol1",
645+
// If this path changes, modify the above command line accordingly (df command).
646+
MountPath: "/mnt/datadir",
647+
},
648+
},
649+
),
650+
).
651+
WithVolumeBuilders(
652+
k8svolume.NewBuilder().
653+
WithName("datavol1").
654+
WithPVCSource(pvcObj.Name),
655+
),
656+
).
657+
Build()
658+
659+
gomega.Expect(err).ShouldNot(gomega.HaveOccurred(), "while building app deployement {%s}", appname)
660+
661+
deployObj, err = DeployClient.WithNamespace(OpenEBSNamespace).Create(deployObj)
662+
gomega.Expect(err).ShouldNot(
663+
gomega.HaveOccurred(),
664+
"while creating pod {%s} in namespace {%s}",
665+
appname,
666+
OpenEBSNamespace,
667+
)
668+
}
669+
670+
func verifyFormatOptionsVerifierPodRunning() {
671+
var err error
672+
appName := "format-options-verifier"
673+
labelValue := fmt.Sprintf("role=test,app=%s", appName)
674+
gomega.Eventually(func() bool {
675+
appPod, err = PodClient.WithNamespace(OpenEBSNamespace).
676+
List(metav1.ListOptions{
677+
LabelSelector: labelValue,
678+
})
679+
gomega.Expect(err).ShouldNot(gomega.HaveOccurred(), "while verifying application pod")
680+
return len(appPod.Items) == 1
681+
},
682+
60, 5).
683+
Should(gomega.BeTrue())
684+
685+
status := IsPodRunningEventually(OpenEBSNamespace, appPod.Items[0].Name)
686+
gomega.Expect(status).To(gomega.Equal(true), "while checking status of pod {%s}", appPod.Items[0].Name)
687+
}
688+
563689
func createDeployVerifyBlockApp() {
564690
ginkgo.By("creating and deploying app pod", createAndDeployBlockAppPod)
565691
ginkgo.By("verifying app pod is running", verifyAppPodRunning)

0 commit comments

Comments
 (0)