From 6e1b371cf151dda14d925ea3c1cfa53a4d5ed439 Mon Sep 17 00:00:00 2001 From: Anton Myagkov Date: Wed, 16 Oct 2024 14:13:19 +0200 Subject: [PATCH] issue-1657: use mount-utils to resize fs (#2056) issue: #1657 Use mount-utils.Resize to support resize of ext4 and xfs --- cloud/blockstore/tests/csi_driver/test.py | 9 ++++++--- cloud/blockstore/tools/csi_driver/client/main.go | 10 +++++++++- .../tools/csi_driver/internal/driver/node.go | 16 ++++++++++++---- .../tools/csi_driver/internal/mounter/iface.go | 3 +++ .../tools/csi_driver/internal/mounter/mock.go | 10 ++++++++++ .../tools/csi_driver/internal/mounter/mounter.go | 15 +++++++++++++-- 6 files changed, 53 insertions(+), 10 deletions(-) diff --git a/cloud/blockstore/tests/csi_driver/test.py b/cloud/blockstore/tests/csi_driver/test.py index ed4e9622bd..d22d92e3fc 100644 --- a/cloud/blockstore/tests/csi_driver/test.py +++ b/cloud/blockstore/tests/csi_driver/test.py @@ -205,7 +205,7 @@ def unstage_volume(self, volume_id: str): volume_id, ) - def publish_volume(self, pod_id: str, volume_id: str, pod_name: str): + def publish_volume(self, pod_id: str, volume_id: str, pod_name: str, fs_type: str = ""): return self._node_run( "publishvolume", "--pod-id", @@ -214,6 +214,8 @@ def publish_volume(self, pod_id: str, volume_id: str, pod_name: str): volume_id, "--pod-name", pod_name, + "--fs-type", + fs_type, ) def unpublish_volume(self, pod_id: str, volume_id: str): @@ -424,7 +426,8 @@ def test_csi_sanity_nbs_backend(mount_path, volume_access_type, vm_mode): cleanup_after_test(env) -def test_node_volume_expand(): +@pytest.mark.parametrize('fs_type', ["ext4", "xfs"]) +def test_node_volume_expand(fs_type): env, run = init() try: volume_name = "example-disk" @@ -433,7 +436,7 @@ def test_node_volume_expand(): pod_id = "deadbeef" env.csi.create_volume(name=volume_name, size=volume_size) env.csi.stage_volume(volume_name) - env.csi.publish_volume(pod_id, volume_name, pod_name) + env.csi.publish_volume(pod_id, volume_name, pod_name, fs_type) new_volume_size = 2 * volume_size env.csi.expand_volume(pod_id, volume_name, new_volume_size) diff --git a/cloud/blockstore/tools/csi_driver/client/main.go b/cloud/blockstore/tools/csi_driver/client/main.go index f7b0e8e87f..79542a3d83 100644 --- a/cloud/blockstore/tools/csi_driver/client/main.go +++ b/cloud/blockstore/tools/csi_driver/client/main.go @@ -253,7 +253,7 @@ func newNodeStageVolumeCommand(endpoint *string) *cobra.Command { } func newPublishVolumeCommand(endpoint *string) *cobra.Command { - var volumeId, podId, stagingTargetPath, podName string + var volumeId, podId, stagingTargetPath, podName, fsType string var readOnly bool cmd := cobra.Command{ Use: "publishvolume", @@ -283,6 +283,7 @@ func newPublishVolumeCommand(endpoint *string) *cobra.Command { "csi.storage.k8s.io/pod.name": podName, "storage.kubernetes.io/csiProvisionerIdentity": "someIdentity", "instanceId": "example-instance-id", + "fsType": fsType, } accessMode := csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER @@ -339,6 +340,13 @@ func newPublishVolumeCommand(endpoint *string) *cobra.Command { false, "volume is read only", ) + cmd.Flags().StringVar( + &fsType, + "fs-type", + "", + "filesystem type: ext4, xfs", + ) + err := cmd.MarkFlagRequired("volume-id") if err != nil { log.Fatal(err) diff --git a/cloud/blockstore/tools/csi_driver/internal/driver/node.go b/cloud/blockstore/tools/csi_driver/internal/driver/node.go index 181936a3f6..5920fbbdc4 100644 --- a/cloud/blockstore/tools/csi_driver/internal/driver/node.go +++ b/cloud/blockstore/tools/csi_driver/internal/driver/node.go @@ -1176,12 +1176,20 @@ func (s *nodeService) NodeExpandVolume( } if s.isMountAccessType(req.VolumePath) { - cmd := exec.Command("resize2fs", nbdDevicePath) - if out, err := cmd.CombinedOutput(); err != nil { + needResize, err := s.mounter.NeedResize(nbdDevicePath, req.VolumePath) + if err != nil { return nil, s.statusErrorf( codes.Internal, - "Failed to resize filesystem %v, output %s", - err, out) + "NeedResize failed %v", err) + } + + if needResize { + _, err := s.mounter.Resize(nbdDevicePath, req.VolumePath) + if err != nil { + return nil, s.statusErrorf( + codes.Internal, + "Failed to resize filesystem %v", err) + } } } diff --git a/cloud/blockstore/tools/csi_driver/internal/mounter/iface.go b/cloud/blockstore/tools/csi_driver/internal/mounter/iface.go index ba767ee375..4a7b9c4651 100644 --- a/cloud/blockstore/tools/csi_driver/internal/mounter/iface.go +++ b/cloud/blockstore/tools/csi_driver/internal/mounter/iface.go @@ -9,4 +9,7 @@ type Interface interface { IsFilesystemExisted(device string) (bool, error) MakeFilesystem(device string, fsType string) ([]byte, error) + + NeedResize(devicePath string, deviceMountPath string) (bool, error) + Resize(devicePath, deviceMountPath string) (bool, error) } diff --git a/cloud/blockstore/tools/csi_driver/internal/mounter/mock.go b/cloud/blockstore/tools/csi_driver/internal/mounter/mock.go index 3bb4e1440c..1ccf0cae02 100644 --- a/cloud/blockstore/tools/csi_driver/internal/mounter/mock.go +++ b/cloud/blockstore/tools/csi_driver/internal/mounter/mock.go @@ -40,6 +40,16 @@ func (c *Mock) MakeFilesystem(device string, fsType string) ([]byte, error) { return args.Get(0).([]byte), args.Error(1) } +func (c *Mock) NeedResize(devicePath string, deviceMountPath string) (bool, error) { + args := c.Called(devicePath, deviceMountPath) + return args.Get(0).(bool), args.Error(1) +} + +func (c *Mock) Resize(devicePath string, deviceMountPath string) (bool, error) { + args := c.Called(devicePath, deviceMountPath) + return args.Get(0).(bool), args.Error(1) +} + //////////////////////////////////////////////////////////////////////////////// func NewMock() *Mock { diff --git a/cloud/blockstore/tools/csi_driver/internal/mounter/mounter.go b/cloud/blockstore/tools/csi_driver/internal/mounter/mounter.go index bb62f43702..af54da1060 100644 --- a/cloud/blockstore/tools/csi_driver/internal/mounter/mounter.go +++ b/cloud/blockstore/tools/csi_driver/internal/mounter/mounter.go @@ -8,17 +8,20 @@ import ( "strings" "k8s.io/mount-utils" + executils "k8s.io/utils/exec" ) //////////////////////////////////////////////////////////////////////////////// type mounter struct { - mnt mount.Interface + mnt mount.Interface + exec executils.Interface } func NewMounter() Interface { return &mounter{ - mnt: mount.New(""), + mnt: mount.New(""), + exec: executils.New(), } } @@ -77,3 +80,11 @@ func (m *mounter) MakeFilesystem(device string, fsType string) ([]byte, error) { options = append(options, device) return exec.Command("mkfs", options...).CombinedOutput() } + +func (m *mounter) NeedResize(devicePath string, deviceMountPath string) (bool, error) { + return mount.NewResizeFs(m.exec).NeedResize(devicePath, deviceMountPath) +} + +func (m *mounter) Resize(devicePath string, deviceMountPath string) (bool, error) { + return mount.NewResizeFs(m.exec).Resize(devicePath, deviceMountPath) +}