Skip to content

Commit

Permalink
reclaimspace: detect Kubernetes version for right StagingTargetPath
Browse files Browse the repository at this point in the history
Kubernetes 1.24 and newer use a different path for staging the volume.
That means the CSI-driver is requested to mount the volume at an other
location, compared to previous versions of Kubernetes. CSI-drivers
implementing the CSI-Addons NodeReclaimSpace procedure, must receive the
correct path, otherwise the driver will not be able to free space and
possibly return an error.

See-also: kubernetes/kubernetes#107065
See-also: https://bugzilla.redhat.com/2096209
Signed-off-by: Niels de Vos <ndevos@redhat.com>
  • Loading branch information
nixpanic committed Jun 15, 2022
1 parent 3612ac1 commit 3f23be1
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion internal/sidecar/service/reclaimspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ package service

import (
"context"
"crypto/sha256"
"fmt"
"path/filepath"
"strconv"

kube "github.com/csi-addons/kubernetes-csi-addons/internal/kubernetes"
"github.com/csi-addons/kubernetes-csi-addons/internal/proto"
Expand Down Expand Up @@ -140,7 +143,13 @@ func (rs *ReclaimSpaceServer) NodeReclaimSpace(
klog.Errorf("Failed to map access mode: %v", err)
return nil, status.Error(codes.InvalidArgument, err.Error())
}
stPath := filepath.Join(rs.stagingPath, "pv", pvName, "globalmount")

stPath, err := rs.getStagingTargetPath(pv)
if err != nil {
klog.Errorf("Failed to get staging target path: %v", err)
return nil, status.Error(codes.Internal, err.Error())
}

accessType := csi.VolumeCapability_Mount{
Mount: &csi.VolumeCapability_MountVolume{},
}
Expand Down Expand Up @@ -189,3 +198,36 @@ func (rs *ReclaimSpaceServer) NodeReclaimSpace(

return res, nil
}

// getStagingTargetPath returns the path where the volume is expected to be
// mounted (or the block-device is attached/mapped). Different Kubernetes
// version use different paths.
func (rs *ReclaimSpaceServer) getStagingTargetPath(pv *corev1.PersistentVolume) (string, error) {
// Kubernetes 1.24+ uses a hash of the volume-id in the path name
unique := sha256.Sum256([]byte(pv.Spec.CSI.VolumeHandle))
targetPath := filepath.Join(rs.stagingPath, pv.Spec.CSI.Driver, fmt.Sprintf("%x", unique), "globalmount")

version, err := rs.kubeClient.Discovery().ServerVersion()
if err != nil {
return "", fmt.Errorf("failed to detect Kubernetes version: %w", err)
}

major, err := strconv.Atoi(version.Major)
if err != nil {
return "", fmt.Errorf("failed to convert Kubernetes major version %q to int: %w", version.Major, err)
}

minor, err := strconv.Atoi(version.Minor)
if err != nil {
return "", fmt.Errorf("failed to convert Kubernetes minor version %q to int: %w", version.Minor, err)
}

// 'encode' major/minor in a single integer
legacyVersion := 1024 // Kubernetes 1.24 => 1 * 1000 + 24
if ((major * 1000) + minor) < (legacyVersion) {
// path in Kubernetes < 1.24
targetPath = filepath.Join(rs.stagingPath, "pv", pv.Name, "globalmount")
}

return targetPath, nil
}

0 comments on commit 3f23be1

Please sign in to comment.