Skip to content

Commit d509325

Browse files
committed
Add file share export paths to volume attributes so that CSI provisioner can add them as PVC annotations
1 parent b4c5aa0 commit d509325

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

pkg/csi/service/common/constants.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,18 @@ const (
144144
// UnknownVolumeType is assigned to CNS volumes whose type couldn't be determined.
145145
UnknownVolumeType = "UNKNOWN"
146146

147+
// Nfsv3AccessPointKey is the key for NFSv3 access point.
148+
Nfsv3AccessPointKey = "NFSv3"
149+
147150
// Nfsv4AccessPointKey is the key for NFSv4 access point.
148151
Nfsv4AccessPointKey = "NFSv4.1"
149152

153+
// Nfsv3ExportPathAnnotationKey specifies the NFSv3 export path annotation key on PVC
154+
Nfsv3ExportPathAnnotationKey = "csi.vsphere.exportpath.nfs3"
155+
156+
// Nfsv4ExportPathAnnotationKey specifies the NFSv4.1 export path annotation key on PVC
157+
Nfsv4ExportPathAnnotationKey = "csi.vsphere.exportpath.nfs41"
158+
150159
// Nfsv4AccessPoint is the access point of file volume.
151160
Nfsv4AccessPoint = "Nfsv4AccessPoint"
152161

pkg/csi/service/wcp/controller.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,34 @@ func (c *controller) createFileVolume(ctx context.Context, req *csi.CreateVolume
15071507
attributes := make(map[string]string)
15081508
attributes[common.AttributeDiskType] = common.DiskTypeFileVolume
15091509

1510+
// Return NFSv3 and NFSv4.1 export paths in volume context attributes.
1511+
// CSI provisioner will add these export paths as PVC annotations.
1512+
// Make a QueryVolume call to fetch file share export paths.
1513+
querySelection := cnstypes.CnsQuerySelection{
1514+
Names: []string{
1515+
string(cnstypes.QuerySelectionNameTypeVolumeType),
1516+
string(cnstypes.QuerySelectionNameTypeBackingObjectDetails),
1517+
},
1518+
}
1519+
volume, err := common.QueryVolumeByID(ctx, c.manager.VolumeManager,
1520+
volumeInfo.VolumeID.Id, &querySelection)
1521+
if err != nil {
1522+
log.Errorf("error while performing QueryVolume on volume %s, error: %+v",
1523+
volumeInfo.VolumeID.Id, err)
1524+
}
1525+
vSANFileBackingDetails := volume.BackingObjectDetails.(*cnstypes.CnsVsanFileShareBackingDetails)
1526+
accessPoints := make(map[string]string)
1527+
for _, kv := range vSANFileBackingDetails.AccessPoints {
1528+
if kv.Key == common.Nfsv3AccessPointKey {
1529+
attributes[common.Nfsv3ExportPathAnnotationKey] = kv.Value
1530+
} else if kv.Key == common.Nfsv4AccessPointKey {
1531+
attributes[common.Nfsv4ExportPathAnnotationKey] = kv.Value
1532+
}
1533+
accessPoints[kv.Key] = kv.Value
1534+
}
1535+
log.Debugf("Access point details for volume: %s, namespace: %s are %+v", req.Name,
1536+
req.Parameters[common.AttributePvcNamespace], accessPoints)
1537+
15101538
resp := &csi.CreateVolumeResponse{
15111539
Volume: &csi.Volume{
15121540
VolumeId: volumeInfo.VolumeID.Id,

pkg/syncer/fullsync.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ const (
6666
annCSIvSphereVolumeAccessibleTopology = "csi.vsphere.volume-accessible-topology"
6767
)
6868

69+
var k8sNewClient = k8s.NewClient
70+
6971
// CsiFullSync reconciles volume metadata on a vanilla k8s cluster with volume
7072
// metadata on CNS.
7173
func CsiFullSync(ctx context.Context, metadataSyncer *metadataSyncInformer, vc string) error {
@@ -224,6 +226,31 @@ func CsiFullSync(ctx context.Context, metadataSyncer *metadataSyncInformer, vc s
224226
}
225227
}
226228

229+
// Iterate over all the file volume PVCs and check if file share export paths are added as annotations
230+
// on it. If not added, then add file share export path annotations on such PVCs.
231+
if metadataSyncer.clusterFlavor == cnstypes.CnsClusterFlavorWorkload {
232+
k8sClient, err := k8sNewClient(ctx)
233+
if err != nil {
234+
log.Errorf("FullSync for VC %s: Failed to create kubernetes client. Err: %+v", vc, err)
235+
return err
236+
}
237+
for _, pv := range k8sPVs {
238+
if IsFileVolume(pv) {
239+
if pvc, ok := pvToPVCMap[pv.Name]; ok {
240+
// Check if file share export path is available as annotation on PVC
241+
if pvc.ObjectMeta.Annotations[common.Nfsv3ExportPathAnnotationKey] == "" {
242+
err = setFileShareAnnotationsOnPVC(ctx, k8sClient, metadataSyncer.volumeManager, pvc)
243+
if err != nil {
244+
log.Errorf("FullSync for VC %s: Failed to add file share export path annotations "+
245+
"for PVC %s, Err: %v. Continuing for other PVCs.", pvc.Name, err)
246+
continue
247+
}
248+
}
249+
}
250+
}
251+
}
252+
}
253+
227254
var queryAllResult *cnstypes.CnsQueryResult
228255
if metadataSyncer.configInfo.Cfg.Global.ClusterID != "" {
229256
// Cluster ID is removed from vSphere Config Secret post 9.0 release in Supervisor
@@ -630,6 +657,57 @@ func patchVolumeAccessibleTopologyToPVC(ctx context.Context, k8sClient clientset
630657
return nil
631658
}
632659

660+
func setFileShareAnnotationsOnPVC(ctx context.Context, k8sClient clientset.Interface,
661+
volumeManager volumes.Manager, pvc *v1.PersistentVolumeClaim) error {
662+
log := logger.GetLogger(ctx)
663+
log.Infof("setFileShareAnnotationsOnPVC: Setting file share annotation for pvc: %q, namespace: %q",
664+
pvc.Name, pvc.Namespace)
665+
666+
pv, err := k8sClient.CoreV1().PersistentVolumes().Get(ctx, pvc.Spec.VolumeName, metav1.GetOptions{})
667+
if err != nil {
668+
log.Errorf("setFileShareAnnotationsOnPVC: Failed to get PV: %q , Err: %v.",
669+
pvc.Spec.VolumeName, err)
670+
return err
671+
}
672+
673+
// Make a QueryVolume call to fetch file share export paths.
674+
querySelection := cnstypes.CnsQuerySelection{
675+
Names: []string{
676+
string(cnstypes.QuerySelectionNameTypeVolumeType),
677+
string(cnstypes.QuerySelectionNameTypeBackingObjectDetails),
678+
},
679+
}
680+
volume, err := common.QueryVolumeByID(ctx, volumeManager, pv.Spec.CSI.VolumeHandle, &querySelection)
681+
if err != nil {
682+
log.Errorf("setFileShareAnnotationsOnPVC: Error while performing QueryVolume on volume %s, Err: %+v",
683+
pv.Spec.CSI.VolumeHandle, err)
684+
}
685+
vSANFileBackingDetails := volume.BackingObjectDetails.(*cnstypes.CnsVsanFileShareBackingDetails)
686+
accessPoints := make(map[string]string)
687+
for _, kv := range vSANFileBackingDetails.AccessPoints {
688+
if kv.Key == common.Nfsv3AccessPointKey {
689+
pvc.Annotations[common.Nfsv3ExportPathAnnotationKey] = kv.Value
690+
} else if kv.Key == common.Nfsv4AccessPointKey {
691+
pvc.Annotations[common.Nfsv4ExportPathAnnotationKey] = kv.Value
692+
}
693+
accessPoints[kv.Key] = kv.Value
694+
}
695+
log.Debugf("setFileShareAnnotationsOnPVC: Access point details for pvc: %q, namespace: %q are %+v",
696+
pvc.Name, pvc.Namespace, accessPoints)
697+
698+
// Update PVC to add annotation on it
699+
pvc, err = k8sClient.CoreV1().PersistentVolumeClaims(pvc.Namespace).Update(ctx, pvc,
700+
metav1.UpdateOptions{})
701+
if err != nil {
702+
log.Errorf("setFileShareAnnotationsOnPVC: Error updating PVC %q in namespace %q, Err: %v",
703+
pvc.Name, pvc.Namespace, err)
704+
return err
705+
}
706+
log.Infof("setFileShareAnnotationsOnPVC: Added file share export paths annotation successfully on PVC %q, "+
707+
"namespce %q", pvc.Name, pvc.Namespace)
708+
return nil
709+
}
710+
633711
// cleanUpVolumeInfoCrDeletionMap removes volumes from the VolumeInfo CR deletion map
634712
// if the volume is present in the K8s cluster.
635713
// This may happen if is not yet created PV by the time full sync

pkg/syncer/syncer_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,15 @@ func runTestCsiFullSync_WorkloadCluster(t *testing.T) {
10131013
commonco.ContainerOrchestratorUtility = originalCO
10141014
}()
10151015

1016+
// Store the original K8sNewclient to restore later
1017+
origK8sClient := k8sNewClient
1018+
defer func() {
1019+
k8sNewClient = origK8sClient
1020+
}()
1021+
k8sNewClient = func(ctx context.Context) (clientset.Interface, error) {
1022+
return k8sclient, nil
1023+
}
1024+
10161025
// Create a WORKLOAD cluster metadataSyncer (note: volumeManagers map is NOT populated)
10171026
// This simulates the real WORKLOAD cluster setup where only volumeManager is set
10181027
workloadMetadataSyncer := &metadataSyncInformer{

0 commit comments

Comments
 (0)