mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-14 02:10:21 +00:00
rbd: implement NodeReclaimSpace
By calling fstrim/blkdiscard on the volume, space consumption should get reduced. Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
parent
7d36c5a9d1
commit
c274649b80
@ -18,10 +18,13 @@ package rbd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
csicommon "github.com/ceph/ceph-csi/internal/csi-common"
|
||||||
rbdutil "github.com/ceph/ceph-csi/internal/rbd"
|
rbdutil "github.com/ceph/ceph-csi/internal/rbd"
|
||||||
"github.com/ceph/ceph-csi/internal/util"
|
"github.com/ceph/ceph-csi/internal/util"
|
||||||
|
|
||||||
|
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||||
rs "github.com/csi-addons/spec/lib/go/reclaimspace"
|
rs "github.com/csi-addons/spec/lib/go/reclaimspace"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
@ -72,3 +75,73 @@ func (rscs *ReclaimSpaceControllerServer) ControllerReclaimSpace(
|
|||||||
|
|
||||||
return &rs.ControllerReclaimSpaceResponse{}, nil
|
return &rs.ControllerReclaimSpaceResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReclaimSpaceNodeServer struct of rbd CSI driver with supported methods
|
||||||
|
// of CSI-addons reclaimspace controller service spec.
|
||||||
|
type ReclaimSpaceNodeServer struct {
|
||||||
|
*rs.UnimplementedReclaimSpaceNodeServer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewReclaimSpaceNodeServer creates a new IdentityServer which handles the
|
||||||
|
// Identity Service requests from the CSI-Addons specification.
|
||||||
|
func NewReclaimSpaceNodeServer() *ReclaimSpaceNodeServer {
|
||||||
|
return &ReclaimSpaceNodeServer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rsns *ReclaimSpaceNodeServer) RegisterService(server grpc.ServiceRegistrar) {
|
||||||
|
rs.RegisterReclaimSpaceNodeServer(server, rsns)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NodeReclaimSpace runs fstrim or blkdiscard on the path where the volume is
|
||||||
|
// mounted or attached. When a volume with multi-node permissions is detected,
|
||||||
|
// an error is returned to prevent potential data corruption.
|
||||||
|
func (rsns *ReclaimSpaceNodeServer) NodeReclaimSpace(
|
||||||
|
ctx context.Context,
|
||||||
|
req *rs.NodeReclaimSpaceRequest) (*rs.NodeReclaimSpaceResponse, error) {
|
||||||
|
// volumeID is a required attribute, it is part of the path to run the
|
||||||
|
// space reducing command on
|
||||||
|
// nolint:ifshort // volumeID is incorrectly assumed to be used only once
|
||||||
|
volumeID := req.GetVolumeId()
|
||||||
|
if volumeID == "" {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "empty volume ID in request")
|
||||||
|
}
|
||||||
|
|
||||||
|
// path can either be the staging path on the node, or the volume path
|
||||||
|
// inside an application container
|
||||||
|
path := req.GetStagingTargetPath()
|
||||||
|
if path == "" {
|
||||||
|
path = req.GetVolumePath()
|
||||||
|
if path == "" {
|
||||||
|
return nil, status.Error(
|
||||||
|
codes.InvalidArgument,
|
||||||
|
"required parameter staging_target_path or volume_path is not set")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// append the right staging location used by this CSI-driver
|
||||||
|
path = fmt.Sprintf("%s/%s", path, volumeID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not allow RWX block-mode volumes, danger of data corruption
|
||||||
|
isBlock, isMultiNode := csicommon.IsBlockMultiNode([]*csi.VolumeCapability{req.GetVolumeCapability()})
|
||||||
|
if isMultiNode {
|
||||||
|
return nil, status.Error(codes.Unimplemented, "multi-node space reclaim is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := "fstrim"
|
||||||
|
if isBlock {
|
||||||
|
cmd = "blkdiscard"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, stderr, err := util.ExecCommand(ctx, cmd, path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(
|
||||||
|
codes.Internal,
|
||||||
|
"failed to execute %q on %q (%s): %s",
|
||||||
|
cmd,
|
||||||
|
path,
|
||||||
|
err.Error(),
|
||||||
|
stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rs.NodeReclaimSpaceResponse{}, nil
|
||||||
|
}
|
||||||
|
@ -41,3 +41,22 @@ func TestControllerReclaimSpace(t *testing.T) {
|
|||||||
_, err := controller.ControllerReclaimSpace(context.TODO(), req)
|
_, err := controller.ControllerReclaimSpace(context.TODO(), req)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestNodeReclaimSpace is a minimal test for the NodeReclaimSpace() procedure.
|
||||||
|
// During unit-testing, there is no Ceph cluster available, so actual
|
||||||
|
// operations can not be performed.
|
||||||
|
func TestNodeReclaimSpace(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
node := NewReclaimSpaceNodeServer()
|
||||||
|
|
||||||
|
req := &rs.NodeReclaimSpaceRequest{
|
||||||
|
VolumeId: "",
|
||||||
|
VolumePath: "",
|
||||||
|
VolumeCapability: nil,
|
||||||
|
Secrets: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := node.NodeReclaimSpace(context.TODO(), req)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user