Skip to content

feat(provisioning): extra format options (mkfs) added #335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/unreleased/335-mhkarimi1383
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
extra format options (mkfs) added

used to add extra options to mkfs while formatting volumes with filesystem
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/sys/mountinfo v0.6.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
Expand All @@ -77,6 +78,7 @@ require (
k8s.io/apiextensions-apiserver v0.27.2 // indirect
k8s.io/gengo v0.0.0-20230306165830-ab3349d207d4 // indirect
k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 // indirect
k8s.io/mount-utils v0.26.15 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/testing_frameworks v0.1.2 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand Down Expand Up @@ -226,6 +227,7 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
Expand All @@ -234,6 +236,7 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
Expand Down Expand Up @@ -261,6 +264,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
Expand All @@ -273,6 +278,7 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
Expand Down Expand Up @@ -830,6 +836,8 @@ k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515 h1:OmK1d0WrkD3IPfkskvroRykOulHVHf0s0ZIFRjyt+UI=
k8s.io/kube-openapi v0.0.0-20230525220651-2546d827e515/go.mod h1:kzo02I3kQ4BTtEfVLaPbjvCkX97YqGve33wzlb3fofQ=
k8s.io/mount-utils v0.26.15 h1:TvTNwRNiXRlxjb7ZUlKObpfINRmcFqMF2i+rb3iJ/co=
k8s.io/mount-utils v0.26.15/go.mod h1:huSg2NI5P8ZNfE8PkQmm5a9fFZ9iHCXFxP/rasMCgYA=
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
Expand Down
5 changes: 5 additions & 0 deletions pkg/driver/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ func GetVolAndMountInfo(
if err != nil {
return nil, nil, err
}
mountinfo.FormatOptions = nil
formatOptions := strings.TrimSpace(req.VolumeContext[lvm.FormatOptionsKey])
if len(formatOptions) > 0 {
mountinfo.FormatOptions = strings.Split(formatOptions, " ")
}

return vol, &mountinfo, nil
}
Expand Down
6 changes: 5 additions & 1 deletion pkg/driver/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,11 @@ func (cs *controller) CreateVolume(
analytics.VolumeProvision)

topology := map[string]string{lvm.LVMTopologyKey: vol.Spec.OwnerNodeID}
cntx := map[string]string{lvm.VolGroupKey: vol.Spec.VolGroup, lvm.OpenEBSCasTypeKey: lvm.LVMCasTypeName}
cntx := map[string]string{
lvm.VolGroupKey: vol.Spec.VolGroup,
lvm.OpenEBSCasTypeKey: lvm.LVMCasTypeName,
lvm.FormatOptionsKey: params.FormatOptions,
}

return csipayload.NewCreateVolumeResponseBuilder().
WithName(volName).
Expand Down
9 changes: 6 additions & 3 deletions pkg/driver/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ type VolumeParams struct {
// extra optional metadata passed by external provisioner
// if enabled. See --extra-create-metadata flag for more details.
// https://github.com/kubernetes-csi/external-provisioner#recommended-optional-arguments
PVCName string
PVCNamespace string
PVName string
PVCName string
PVCNamespace string
PVName string
FormatOptions string
}

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

params.FormatOptions = m["formatoptions"]

var err error
if params.VgPattern, err = regexp.Compile(vgPattern); err != nil {
return nil, fmt.Errorf("invalid volgroup/vgpattern param %v: %v", vgPattern, err)
Expand Down
15 changes: 13 additions & 2 deletions pkg/lvm/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"k8s.io/klog/v2"
"k8s.io/mount-utils"
utilexec "k8s.io/utils/exec"
"k8s.io/utils/mount"

apis "github.com/openebs/lvm-localpv/pkg/apis/openebs.io/lvm/v1alpha1"
)
Expand All @@ -53,6 +53,10 @@ type MountInfo struct {
// MountOptions specifies the options with
// which mount needs to be attempted
MountOptions []string `json:"mountOptions"`

// FormatOptions specifies the options that
// will be added to newly created volume on first use
FormatOptions []string `json:"formatOptions"`
}

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

err := mounter.FormatAndMount(devicePath, mountInfo.MountPath, mountInfo.FSType, mountInfo.MountOptions)
err := mounter.FormatAndMountSensitiveWithFormatOptions(
devicePath,
mountInfo.MountPath,
mountInfo.FSType,
mountInfo.MountOptions,
nil, // sensitiveOptions
mountInfo.FormatOptions,
)
if err != nil {
klog.Errorf(
"lvm: failed to mount volume %s [%s] to %s, error %v",
Expand Down
2 changes: 2 additions & 0 deletions pkg/lvm/volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ const (
OpenEBSCasTypeKey string = "openebs.io/cas-type"
// LVMCasTypeName for the name of the cas-type
LVMCasTypeName string = "localpv-lvm"
// FormatOptionsKey for Extra Format Options in storage class
FormatOptionsKey string = "openebs.io/format-options"
)

var (
Expand Down
17 changes: 17 additions & 0 deletions tests/provision_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,22 @@ func fsVolCreationTest() {
}
}

func formatOptionsTest() {
formatOptions := "-b 4096 -N 5000000"
By("####### Creating the storage class with formatOptions : " + formatOptions + " #######")
createFormatOptionsStorageClass(formatOptions)
By("Creating and verifying PVC bound status")
createAndVerifyPVC(true)
By("Creating and deploying app pod", createDeployVerifyFormatOptions)
By("Verifying LVMVolume object to be Ready")
VerifyLVMVolume(true, "")
By("Deleting verifier pvc/pod")
deleteAppAndPvc([]string{"format-options-verifier"}, pvcName)
By("Verifying that PV is deleted after deletion")
verifyPVForPVC(false, pvcName)
By("Deleting storage class", deleteStorageClass)
}

func blockVolCreationTest() {
By("Creating default storage class", createStorageClass)
By("Creating and verifying PVC bound status")
Expand Down Expand Up @@ -321,6 +337,7 @@ func volumeCreationTest() {
device := setupVg(40, "lvmvg")
defer cleanupVg(device, "lvmvg")
By("###Running filesystem volume creation test###", fsVolCreationTest)
By("###Running filesystem with formatOptions creation test###", formatOptionsTest)
By("###Running block volume creation test###", blockVolCreationTest)
By("###Running thin volume creation test###", thinVolCreationTest)
By("###Running leak protection test###", leakProtectionTest)
Expand Down
126 changes: 126 additions & 0 deletions tests/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,29 @@ func createThinStorageClass() {
gomega.Expect(err).To(gomega.BeNil(), "while creating a thinProvision storageclass {%s}", scName)
}

func createFormatOptionsStorageClass(formatOptions string) {
var (
err error
)

parameters := map[string]string{
"volgroup": VOLGROUP,
"formatOptions": formatOptions,
}

ginkgo.By("building a default storage class")
scObj, err = sc.NewBuilder().
WithGenerateName(scName).
WithVolumeExpansion(true).
WithParametersNew(parameters).
WithProvisioner(LocalProvisioner).Build()
gomega.Expect(err).ShouldNot(gomega.HaveOccurred(),
"while building formatOptions storageclass obj with prefix {%s}", scName)

scObj, err = SCClient.Create(scObj)
gomega.Expect(err).To(gomega.BeNil(), "while creating a storageclass with formatOptions {%s}", scName)
}

// VerifyLVMVolume verify the properties of a lvm-volume
// expected_vg is supposed to be passed only when vgpatten was used for scheduling.
// If its volgroup in sc then we can just match volgroup with lvmvolume's vg field.
Expand Down Expand Up @@ -560,6 +583,109 @@ func createAndDeployBlockAppPod() {
}
}

func createDeployVerifyFormatOptions() {
ginkgo.By("creating and deploying verifier pod")
createAndDeployVerifyFormatOptions()
ginkgo.By("verifying verifier pod is running", verifyFormatOptionsVerifierPodRunning)
}

func createAndDeployVerifyFormatOptions() {
var err error
appname := "format-options-verifier"
labels := map[string]string{
"role": "test",
"app": appname,
}
ginkgo.By("building app " + appname + " using above lvm volume")
deployObj, err = deploy.NewBuilder().
WithName(appname).
WithNamespace(OpenEBSNamespace).
WithLabelsNew(labels).
WithSelectorMatchLabelsNew(labels).
WithPodTemplateSpecBuilder(
pts.NewBuilder().
WithLabelsNew(labels).
WithContainerBuilders(
container.NewBuilder().
WithImage("debian:stable-slim").
WithName("verifier").
WithImagePullPolicy(corev1.PullIfNotPresent).
WithEnvsNew(
[]corev1.EnvVar{
{
Name: "MIN_INODES",
Value: "5000000",
},
},
).
WithCommandNew(
[]string{
"bash",
"-c",
`test "$(df -i '/mnt/datadir' | tail -n 1 | awk '{print $2}')" -ge "$MIN_INODES" && tail -f /dev/null`,
},
).
WithLifeCycle(
&corev1.Lifecycle{
PreStop: &corev1.LifecycleHandler{
Exec: &corev1.ExecAction{
Command: []string{
"bash",
"-c",
"kill -9 $(pidof tail)",
},
},
},
},
).
WithVolumeMountsNew(
[]corev1.VolumeMount{
{
Name: "datavol1",
// If this path changes, modify the above command line accordingly (df command).
MountPath: "/mnt/datadir",
},
},
),
).
WithVolumeBuilders(
k8svolume.NewBuilder().
WithName("datavol1").
WithPVCSource(pvcObj.Name),
),
).
Build()

gomega.Expect(err).ShouldNot(gomega.HaveOccurred(), "while building app deployement {%s}", appname)

deployObj, err = DeployClient.WithNamespace(OpenEBSNamespace).Create(deployObj)
gomega.Expect(err).ShouldNot(
gomega.HaveOccurred(),
"while creating pod {%s} in namespace {%s}",
appname,
OpenEBSNamespace,
)
}

func verifyFormatOptionsVerifierPodRunning() {
var err error
appName := "format-options-verifier"
labelValue := fmt.Sprintf("role=test,app=%s", appName)
gomega.Eventually(func() bool {
appPod, err = PodClient.WithNamespace(OpenEBSNamespace).
List(metav1.ListOptions{
LabelSelector: labelValue,
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred(), "while verifying application pod")
return len(appPod.Items) == 1
},
60, 5).
Should(gomega.BeTrue())

status := IsPodRunningEventually(OpenEBSNamespace, appPod.Items[0].Name)
gomega.Expect(status).To(gomega.Equal(true), "while checking status of pod {%s}", appPod.Items[0].Name)
}

func createDeployVerifyBlockApp() {
ginkgo.By("creating and deploying app pod", createAndDeployBlockAppPod)
ginkgo.By("verifying app pod is running", verifyAppPodRunning)
Expand Down
Loading