@@ -18,6 +18,7 @@ import (
1818 "google.golang.org/grpc/status"
1919 apps_v1 "k8s.io/api/apps/v1"
2020 core_v1 "k8s.io/api/core/v1"
21+ rbac_v1 "k8s.io/api/rbac/v1"
2122 "k8s.io/apimachinery/pkg/api/errors"
2223 "k8s.io/apimachinery/pkg/api/resource"
2324 meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -36,38 +37,48 @@ const (
3637 defaultRLimitMemory = "2Gi"
3738 defaultRRequestMemory = "512Mi"
3839
39- creationInterval = 60 // 300s with sleep interval of 5s
40- creationDelay = 5 * time .Second
41- defaultExportPath = "/export"
42- nfsResourceLimitsCPUKey = "nfsResourceLimitsCpuM"
43- nfsResourceRequestsCPUKey = "nfsResourceRequestsCpuM"
44- nfsResourceLimitsMemoryKey = "nfsResourceLimitsMemoryMi"
45- nfsResourceRequestsMemoryKey = "nfsResourceRequestsMemoryMi"
46- nfsMountOptionsKey = "nfsMountOptions"
47- nfsResourceLabelKey = "nfsResourceLabel"
48- nfsNodeSelectorKey = "csi.hpe.com/hpe-nfs"
49- nfsNodeSelectorDefaultValue = "true"
50- nfsNodeSelectorParamKey = "nfsNodeSelector"
51- nfsParentVolumeIDKey = "nfs-parent-volume-id"
52- nfsNamespaceKey = "nfsNamespace"
53- nfsSourceNamespaceKey = "csi.storage.k8s.io/pvc/namespace"
54- nfsSourcePVCNameKey = "csi.storage.k8s.io/pvc/name"
55- nfsProvisionerImageKey = "nfsProvisionerImage"
56- pvcKind = "PersistentVolumeClaim"
57- nfsConfigFile = "ganesha.conf"
58- nfsConfigMap = "hpe-nfs-config"
59- nfsServiceAccount = "hpe-csi-nfs-sa"
60- defaultPodLabelKey = "monitored-by"
61- defaultPodLabelValue = "hpe-csi"
62- nfsAffinityLabelKey = "spread-by"
63- nfsAffinityLabelValue = "hpe-nfs"
64- nfsDedicatedTolerationKey = "csi.hpe.com/hpe-nfs"
65- nfsProvisionedByKey = "provisioned-by"
66- nfsProvisionedFromKey = "provisioned-from"
67- nfsForeignStorageClassKey = "nfsForeignStorageClass"
68- nfsResourcesKey = "nfsResources"
69- nfsTolerationSecScKey = "nfsTolerationSeconds"
70- defaultNfsTolerationSeconds = 30
40+ creationInterval = 60 // 300s with sleep interval of 5s
41+ creationDelay = 5 * time .Second
42+ defaultExportPath = "/export"
43+ nfsResourceLimitsCPUKey = "nfsResourceLimitsCpuM"
44+ nfsResourceRequestsCPUKey = "nfsResourceRequestsCpuM"
45+ nfsResourceLimitsMemoryKey = "nfsResourceLimitsMemoryMi"
46+ nfsResourceRequestsMemoryKey = "nfsResourceRequestsMemoryMi"
47+ nfsMountOptionsKey = "nfsMountOptions"
48+ nfsResourceLabelKey = "nfsResourceLabel"
49+ nfsNodeSelectorKey = "csi.hpe.com/hpe-nfs"
50+ nfsNodeSelectorDefaultValue = "true"
51+ nfsNodeSelectorParamKey = "nfsNodeSelector"
52+ nfsParentVolumeIDKey = "nfs-parent-volume-id"
53+ nfsNamespaceKey = "nfsNamespace"
54+ nfsSourceNamespaceKey = "csi.storage.k8s.io/pvc/namespace"
55+ nfsSourcePVCNameKey = "csi.storage.k8s.io/pvc/name"
56+ nfsProvisionerImageKey = "nfsProvisionerImage"
57+ pvcKind = "PersistentVolumeClaim"
58+ nfsConfigFile = "ganesha.conf"
59+ nfsConfigMap = "hpe-nfs-config"
60+ nfsServiceAccount = "hpe-csi-nfs-sa"
61+ defaultPodLabelKey = "monitored-by"
62+ defaultPodLabelValue = "hpe-csi"
63+ nfsAffinityLabelKey = "spread-by"
64+ nfsAffinityLabelValue = "hpe-nfs"
65+ nfsDedicatedTolerationKey = "csi.hpe.com/hpe-nfs"
66+ nfsProvisionedByKey = "provisioned-by"
67+ nfsProvisionedFromKey = "provisioned-from"
68+ nfsForeignStorageClassKey = "nfsForeignStorageClass"
69+ nfsResourcesKey = "nfsResources"
70+ nfsTolerationSecScKey = "nfsTolerationSeconds"
71+ defaultNfsTolerationSeconds = 30
72+ nfsProbeInitialDelaySeconds = 0
73+ nfsProbePeriodSeconds = 10
74+ nfsProbeTimeoutSeconds = 5
75+ nfsLivenessProbePeriodSeconds = 30
76+ nfsLivenessProbeTimeoutSeconds = 90
77+ nfsProbeReadinessKey = "READINESS"
78+ nfsProbeStartupKey = "STARTUP"
79+ nfsProbeLivenessKey = "LIVENESS"
80+ nfsRoleBindingSuffix = "-deployment-rollout-binding"
81+ nfsRoleSuffix = "-deployment-rollout-role"
7182)
7283
7384// NFSSpec for creating NFS resources
@@ -152,6 +163,13 @@ func (flavor *Flavor) CreateNFSVolume(pvName string, reqVolSize int64, parameter
152163 return nil , true , err
153164 }
154165
166+ log .Tracef ("Create a role and role binding for the pv %s and service account %s" , pvName , nfsServiceAccount )
167+ err = flavor .createRoleAndRoleBinding (pvName , nfsServiceAccount , nfsResourceNamespace )
168+ if err != nil {
169+ log .Errorf ("error occured while creating the role and rolebinding for the service account %s:%s" , nfsServiceAccount , err .Error ())
170+ return nil , true , fmt .Errorf ("error occured while creating the role and rolebinding for the service account %s:%s" , nfsServiceAccount , err .Error ())
171+ }
172+
155173 // create deployment with name hpe-nfs-<originalclaim-uid>
156174 deploymentName := fmt .Sprintf ("%s%s" , nfsPrefix , claim .ObjectMeta .UID )
157175 err = flavor .createNFSDeployment (deploymentName , nfsSpec , nfsResourceNamespace )
@@ -221,6 +239,71 @@ func (flavor *Flavor) createServiceAccount(nfsNamespace string) error {
221239 return nil
222240}
223241
242+ func (flavor * Flavor ) createRoleAndRoleBinding (pvName , nfsServiceAccount , nfsNamespace string ) error {
243+ log .Tracef (">>>>> createRoleAndRoleBinding for PV %s and ServiceAccount %s under namespace %s" , pvName , nfsServiceAccount , nfsNamespace )
244+ defer log .Tracef ("<<<<< createRoleAndRoleBinding" )
245+
246+ pvName = strings .TrimPrefix (pvName , "pvc-" )
247+ roleName := nfsPrefix + pvName + nfsRoleSuffix
248+ role := & rbac_v1.Role {
249+ ObjectMeta : meta_v1.ObjectMeta {
250+ Name : roleName ,
251+ Namespace : nfsNamespace ,
252+ },
253+ Rules : []rbac_v1.PolicyRule {
254+ {
255+ APIGroups : []string {"apps" },
256+ Resources : []string {"deployments" },
257+ Verbs : []string {"update" , "patch" , "list" , "get" },
258+ },
259+ },
260+ }
261+
262+ _ , err := flavor .kubeClient .RbacV1 ().Roles (nfsNamespace ).Create (context .Background (), role , meta_v1.CreateOptions {})
263+ if err != nil {
264+ if errors .IsAlreadyExists (err ) {
265+ log .Infof ("Role %s already exists." , roleName )
266+ } else {
267+ log .Errorf ("Error occured while creating the role for ServiceAccount %s:%s" , nfsServiceAccount , err .Error ())
268+ return err
269+ }
270+ } else {
271+ log .Infof ("Role %s for the the ServiceAccount %s created successfully" , roleName , nfsServiceAccount )
272+ }
273+
274+ roleBindingName := nfsPrefix + pvName + nfsRoleBindingSuffix
275+ roleBinding := & rbac_v1.RoleBinding {
276+ ObjectMeta : meta_v1.ObjectMeta {
277+ Name : roleBindingName ,
278+ Namespace : nfsNamespace ,
279+ },
280+ Subjects : []rbac_v1.Subject {
281+ {
282+ Kind : "ServiceAccount" ,
283+ Name : nfsServiceAccount ,
284+ Namespace : nfsNamespace ,
285+ },
286+ },
287+ RoleRef : rbac_v1.RoleRef {
288+ Kind : "Role" ,
289+ Name : roleName ,
290+ APIGroup : "rbac.authorization.k8s.io" ,
291+ },
292+ }
293+ _ , err = flavor .kubeClient .RbacV1 ().RoleBindings (nfsNamespace ).Create (context .Background (), roleBinding , meta_v1.CreateOptions {})
294+ if err != nil {
295+ if errors .IsAlreadyExists (err ) {
296+ log .Infof ("RoleBinding %s already exists." , roleBinding )
297+ return nil
298+ } else {
299+ log .Errorf ("Error occured while creating the role binding for ServiceAccount %s:%s" , nfsServiceAccount , err .Error ())
300+ return err
301+ }
302+ }
303+ log .Infof (" RoleBinding '%s for the ServiceAccount %s created successfully." , roleBindingName , nfsServiceAccount )
304+ return nil
305+ }
306+
224307func (flavor * Flavor ) createNFSConfigMap (nfsNamespace , hostDomain string ) error {
225308 log .Tracef (">>>>> createNFSConfigMap with namespace %s, domain %s" , nfsNamespace , hostDomain )
226309 defer log .Tracef ("<<<<< createNFSConfigMap" )
@@ -279,7 +362,7 @@ EXPORT
279362func (flavor * Flavor ) RollbackNFSResources (nfsResourceName string , nfsNamespace string ) error {
280363 log .Tracef (">>>>> RollbackNFSResources with name %s namespace %s" , nfsResourceName , nfsNamespace )
281364 defer log .Tracef ("<<<<< RollbackNFSResources" )
282- err := flavor .deleteNFSResources (nfsResourceName , nfsNamespace )
365+ err := flavor .deleteNFSResources ("" , nfsResourceName , nfsNamespace )
283366 if err != nil {
284367 return err
285368 }
@@ -299,15 +382,15 @@ func (flavor *Flavor) DeleteNFSVolume(volumeID string) error {
299382 if err != nil {
300383 return err
301384 }
302- err = flavor .deleteNFSResources (nfsResourceName , nfsNamespace )
385+ err = flavor .deleteNFSResources (volumeID , nfsResourceName , nfsNamespace )
303386 if err != nil {
304387 return err
305388 }
306389
307390 return err
308391}
309392
310- func (flavor * Flavor ) deleteNFSResources (nfsResourceName , nfsNamespace string ) (err error ) {
393+ func (flavor * Flavor ) deleteNFSResources (volumeID , nfsResourceName , nfsNamespace string ) (err error ) {
311394 // delete deployment deployment/hpe-nfs-<originalclaim-uid>
312395 err = flavor .deleteNFSDeployment (nfsResourceName , nfsNamespace )
313396 if err != nil {
@@ -326,9 +409,45 @@ func (flavor *Flavor) deleteNFSResources(nfsResourceName, nfsNamespace string) (
326409 if err != nil {
327410 log .Errorf ("unable to delete nfs service %s as part of cleanup, err %s" , nfsResourceName , err .Error ())
328411 }
412+
413+ roleName := nfsPrefix + volumeID + nfsRoleSuffix
414+ err = flavor .deleteNFSRole (volumeID , roleName , nfsNamespace )
415+ if err != nil {
416+ log .Errorf ("unable to delete role %s as part of cleanup, err %s" , roleName , err .Error ())
417+ }
418+
419+ roleBindingName := nfsPrefix + volumeID + nfsRoleBindingSuffix
420+ err = flavor .deleteNFSRoleBinding (volumeID , roleBindingName , nfsNamespace )
421+ if err != nil {
422+ log .Errorf ("unable to delete role binding %s as part of cleanup, err %s" , roleBindingName , err .Error ())
423+ }
329424 return err
330425}
331426
427+ func (flavor * Flavor ) deleteNFSRole (volumeID , roleName , nfsNamespace string ) error {
428+ log .Tracef (">>>>> deleteNFSRole for the volume %s" , volumeID )
429+ defer log .Tracef ("<<<<< deleteNFSRole" )
430+ err := flavor .kubeClient .RbacV1 ().Roles (nfsNamespace ).Delete (context .Background (), roleName , meta_v1.DeleteOptions {})
431+ if err != nil && ! errors .IsNotFound (err ) {
432+ log .Errorf ("failed to delete the role %s for volume %s, err %+v" , roleName , volumeID , err )
433+ return err
434+ }
435+ log .Infof ("Triggered deletion of role %s" , roleName )
436+ return nil
437+ }
438+
439+ func (flavor * Flavor ) deleteNFSRoleBinding (volumeID , roleBindingName , nfsNamespace string ) error {
440+ log .Tracef (">>>>> deleteNFSRoleBinding for the volume %s" , volumeID )
441+ defer log .Tracef ("<<<<< deleteNFSRoleBinding" )
442+ err := flavor .kubeClient .RbacV1 ().RoleBindings (nfsNamespace ).Delete (context .Background (), roleBindingName , meta_v1.DeleteOptions {})
443+ if err != nil && ! errors .IsNotFound (err ) {
444+ log .Errorf ("failed to delete the role binding %s for volume %s, err %+v" , roleBindingName , volumeID , err )
445+ return err
446+ }
447+ log .Infof ("Triggered deletion of role binding %s" , roleBindingName )
448+ return nil
449+ }
450+
332451func (flavor * Flavor ) getNFSResourceNameByVolumeID (volumeID string ) (string , error ) {
333452 // get underlying by NFS(RWX) PV volume-id
334453 pv , err := flavor .getPVByNFSLabel (nfsParentVolumeIDKey , volumeID )
@@ -907,6 +1026,44 @@ func (flavor *Flavor) makeNFSDeployment(name string, nfsSpec *NFSSpec, nfsNamesp
9071026 LabelSelector : & podLabelSelector ,
9081027 }
9091028
1029+ startupProbe := & core_v1.Probe {
1030+ ProbeHandler : core_v1.ProbeHandler {
1031+ Exec : & core_v1.ExecAction {
1032+ Command : []string {"/bin/sh" , "/nfsHealthCheck.sh" , nfsProbeStartupKey },
1033+ },
1034+ },
1035+ InitialDelaySeconds : nfsProbeInitialDelaySeconds ,
1036+ PeriodSeconds : nfsProbePeriodSeconds ,
1037+ TimeoutSeconds : nfsProbeTimeoutSeconds ,
1038+ }
1039+
1040+ readinessProbe := & core_v1.Probe {
1041+ ProbeHandler : core_v1.ProbeHandler {
1042+ Exec : & core_v1.ExecAction {
1043+ Command : []string {"/bin/sh" , "/nfsHealthCheck.sh" , nfsProbeReadinessKey },
1044+ },
1045+ },
1046+ InitialDelaySeconds : nfsProbeInitialDelaySeconds ,
1047+ PeriodSeconds : nfsProbePeriodSeconds ,
1048+ TimeoutSeconds : nfsProbeTimeoutSeconds ,
1049+ }
1050+
1051+ livenessProbe := & core_v1.Probe {
1052+ ProbeHandler : core_v1.ProbeHandler {
1053+ Exec : & core_v1.ExecAction {
1054+ Command : []string {"/bin/sh" , "/nfsHealthCheck.sh" , nfsProbeLivenessKey },
1055+ },
1056+ },
1057+ InitialDelaySeconds : nfsProbeInitialDelaySeconds ,
1058+ PeriodSeconds : nfsLivenessProbePeriodSeconds ,
1059+ TimeoutSeconds : nfsLivenessProbeTimeoutSeconds ,
1060+ }
1061+
1062+ containers := []core_v1.Container {flavor .makeContainer ("hpe-nfs" , nfsSpec )}
1063+ containers [0 ].StartupProbe = startupProbe
1064+ containers [0 ].ReadinessProbe = readinessProbe
1065+ containers [0 ].LivenessProbe = livenessProbe
1066+
9101067 podSpec := core_v1.PodTemplateSpec {
9111068 ObjectMeta : meta_v1.ObjectMeta {
9121069 Name : name ,
@@ -915,7 +1072,7 @@ func (flavor *Flavor) makeNFSDeployment(name string, nfsSpec *NFSSpec, nfsNamesp
9151072 },
9161073 Spec : core_v1.PodSpec {
9171074 ServiceAccountName : nfsServiceAccount ,
918- Containers : []core_v1. Container { flavor . makeContainer ( "hpe-nfs" , nfsSpec )} ,
1075+ Containers : containers ,
9191076 RestartPolicy : core_v1 .RestartPolicyAlways ,
9201077 Volumes : volumes ,
9211078 HostIPC : false ,
0 commit comments