rbd: discover if StagingTargetPath in NodeExpandVolume

The StagingTargetPath is an optional entry in
NodeExpandVolumeRequest, We cannot expect it to be
set always and at the same time cephcsi depended
on the StaingTargetPath to retrieve some metadata
information.

This commit will check all the mount ref and identifies
the stagingTargetPath by checking the image-meta.json
file exists and this is a costly operation as we need to
loop through all the mounts and check image-meta.json
in each mount but this is happens only if the
StaingTargetPath is not set in the NodeExpandVolumeRequest

fixes #3623

Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
Madhu Rajanna 2023-01-27 10:33:01 +01:00 committed by mergify[bot]
parent a4fac623ff
commit e54a97ba85
2 changed files with 47 additions and 6 deletions

View File

@ -1026,6 +1026,29 @@ func (ns *NodeServer) NodeUnstageVolume(
return &csi.NodeUnstageVolumeResponse{}, nil
}
// getStagingPath returns the staging path for the volume from the volume path.
// The staingTargetPath looks like
// /var/lib/kubelet/plugins/kubernetes.io/csi/pv/pvc-08937eb8-7e00-4033-b6ce-bc36147b4ed0/
// globalmount/0001-0009-rook-ceph-0000000000000002-50d53503-9da1-11ed-847e-bacf8f2f1297
// the last directory is the volumeID returned in the NodeStageVolumeRespose.
// The image-meta.json file is present in the staging path without volumeID.
func (ns *NodeServer) getStagingPath(volPath string) (string, error) {
mounts, err := ns.Mounter.GetMountRefs(volPath)
if err != nil {
return "", err
}
for _, mount := range mounts {
// strip the last directory from the staging path
stp := strings.Split(mount, "/")
stagingTargetPath := strings.Join(stp[:len(stp)-1], "/")
if checkRBDImageMetadataStashExists(stagingTargetPath) {
return stagingTargetPath, nil
}
}
return "", fmt.Errorf("failed to get staging path for volume %s", volPath)
}
// NodeExpandVolume resizes rbd volumes.
func (ns *NodeServer) NodeExpandVolume(
ctx context.Context,
@ -1042,8 +1065,18 @@ func (ns *NodeServer) NodeExpandVolume(
volumePath := req.GetStagingTargetPath()
if volumePath == "" {
// If Kubernetes version < v1.19.0 the volume_path would be
// having the staging_target_path information
// having the staging_target_path information.
// stagingTargetPath is optional parameter in NodeExpandVolumeRequest request
// Kubernetes will not send the staging_target_path in the volume_path in some cases
// Refer https://github.com/kubernetes/kubernetes/issues/115343
var err error
volumePath, err = ns.getStagingPath(req.GetVolumePath())
if err != nil {
// If stagingTargetPath is not found in volumePath then use
// volumePath
volumePath = req.GetVolumePath()
log.UsefulLog(ctx, "failed to find stagingTargetPath from volumePath %v: %v", volumePath, err)
}
}
if volumePath == "" {
return nil, status.Error(codes.InvalidArgument, "volume path must be provided")

View File

@ -1731,6 +1731,14 @@ func stashRBDImageMetadata(volOptions *rbdVolume, metaDataPath string) error {
return nil
}
// checkRBDImageMetadataStashExists checks if the stashFile exists at the passed in path.
func checkRBDImageMetadataStashExists(metaDataPath string) bool {
imageMetaPath := filepath.Join(metaDataPath, stashFileName)
_, err := os.Stat(imageMetaPath)
return err == nil
}
// lookupRBDImageMetadataStash reads and returns stashed image metadata at passed in path.
func lookupRBDImageMetadataStash(metaDataPath string) (rbdImageMetadataStash, error) {
var imgMeta rbdImageMetadataStash