Skip to content

Commit a4a50ea

Browse files
mooneksilvacarloss
authored andcommitted
[manila-csi-plugin] support muilple share rules
Signed-off-by: moonek <[email protected]> Signed-off-by: Carlos da Silva <[email protected]>
1 parent b55fbc4 commit a4a50ea

File tree

9 files changed

+114
-84
lines changed

9 files changed

+114
-84
lines changed

docs/manila-csi-plugin/using-manila-csi-plugin.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ Parameter | Required | Description
7171
----------|----------|------------
7272
`shareID` | if `shareName` is not given | The UUID of the share
7373
`shareName` | if `shareID` is not given | The name of the share
74-
`shareAccessID` | _yes_ | The UUID of the access rule for the share
74+
`shareAccessIDs` | _yes_ | The UUID of the access rule for the share
7575
`cephfs-mounter` | _no_ | Relevant for CephFS Manila shares. Specifies which mounting method to use with the CSI CephFS driver. Available options are `kernel` and `fuse`, defaults to `fuse`. See [CSI CephFS docs](https://github.com/ceph/ceph-csi/blob/csi-v1.0/docs/deploy-cephfs.md#configuration) for further information.
7676
`cephfs-kernelMountOptions` | _no_ | Relevant for CephFS Manila shares. Specifies mount options for CephFS kernel client. See [CSI CephFS docs](https://github.com/ceph/ceph-csi/blob/csi-v1.0/docs/deploy-cephfs.md#configuration) for further information.
7777
`cephfs-fuseMountOptions` | _no_ | Relevant for CephFS Manila shares. Specifies mount options for CephFS FUSE client. See [CSI CephFS docs](https://github.com/ceph/ceph-csi/blob/csi-v1.0/docs/deploy-cephfs.md#configuration) for further information.

examples/manila-csi-plugin/nfs/static-provisioning/preprovisioned-pvc.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ spec:
2020
namespace: default
2121
volumeAttributes:
2222
shareID: SHARE-UUID-GOES-HERE
23-
shareAccessID: ACCESS-UUID-OF-THE-SHARE
23+
shareAccessIDs: ACCESS-UUID-OF-THE-SHARE
2424
---
2525
apiVersion: v1
2626
kind: PersistentVolumeClaim

pkg/csi/manila/controllerserver.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,24 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
194194

195195
ad := getShareAdapter(shareOpts.Protocol)
196196

197-
accessRight, err := ad.GetOrGrantAccess(ctx, &shareadapters.GrantAccessArgs{Share: share, ManilaClient: manilaClient, Options: shareOpts})
197+
accessRights, err := ad.GetOrGrantAccesses(ctx, &shareadapters.GrantAccessArgs{Share: share, ManilaClient: manilaClient, Options: shareOpts})
198198
if err != nil {
199199
if wait.Interrupted(err) {
200-
return nil, status.Errorf(codes.DeadlineExceeded, "deadline exceeded while waiting for access rule %s for volume %s to become available", accessRight.ID, share.Name)
200+
return nil, status.Errorf(codes.DeadlineExceeded, "deadline exceeded while waiting for access rules for volume %s to become available", share.Name)
201201
}
202202

203203
return nil, status.Errorf(codes.Internal, "failed to grant access to volume %s: %v", share.Name, err)
204204
}
205205

206+
var accessRightIDs []string
207+
for _, ar := range accessRights {
208+
accessRightIDs = append(accessRightIDs, ar.ID)
209+
}
210+
shareAccessIDs := strings.Join(accessRightIDs, ",")
211+
206212
volCtx := filterParametersForVolumeContext(params, options.NodeVolumeContextFields())
207213
volCtx = util.SetMapIfNotEmpty(volCtx, "shareID", share.ID)
208-
volCtx = util.SetMapIfNotEmpty(volCtx, "shareAccessID", accessRight.ID)
214+
volCtx = util.SetMapIfNotEmpty(volCtx, "shareAccessIDs", shareAccessIDs)
209215
volCtx = util.SetMapIfNotEmpty(volCtx, "groupID", share.ShareGroupID)
210216
volCtx = util.SetMapIfNotEmpty(volCtx, "affinity", shareOpts.Affinity)
211217
volCtx = util.SetMapIfNotEmpty(volCtx, "antiAffinity", shareOpts.AntiAffinity)

pkg/csi/manila/nodeserver.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,15 @@ func (ns *nodeServer) buildVolumeContext(ctx context.Context, volID volumeID, sh
109109
}
110110

111111
for i := range accessRights {
112-
if accessRights[i].ID == shareOpts.ShareAccessID {
112+
if accessRights[i].ID == shareOpts.ShareAccessIDs {
113113
accessRight = &accessRights[i]
114114
break
115115
}
116116
}
117117

118118
if accessRight == nil {
119-
return nil, nil, status.Errorf(codes.InvalidArgument, "cannot find access right %s for volume %s",
120-
shareOpts.ShareAccessID, volID)
119+
return nil, nil, status.Errorf(codes.InvalidArgument, "cannot find access rights %s for volume %s",
120+
shareOpts.ShareAccessIDs, volID)
121121
}
122122

123123
// Retrieve list of all export locations for this share.

pkg/csi/manila/options/shareoptions.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ type ControllerVolumeContext struct {
4141
}
4242

4343
type NodeVolumeContext struct {
44-
ShareID string `name:"shareID" value:"optionalIf:shareName=." precludes:"shareName"`
45-
ShareName string `name:"shareName" value:"optionalIf:shareID=." precludes:"shareID"`
46-
ShareAccessID string `name:"shareAccessID"`
44+
ShareID string `name:"shareID" value:"optionalIf:shareName=." precludes:"shareName"`
45+
ShareName string `name:"shareName" value:"optionalIf:shareID=." precludes:"shareID"`
46+
ShareAccessIDs string `name:"shareAccessIDs"`
4747

4848
// Adapter options
4949

pkg/csi/manila/shareadapters/cephfs.go

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package shareadapters
1919
import (
2020
"context"
2121
"fmt"
22+
"strings"
2223
"time"
2324

2425
"github.com/gophercloud/gophercloud/v2"
@@ -32,82 +33,84 @@ type Cephfs struct{}
3233

3334
var _ ShareAdapter = &Cephfs{}
3435

35-
func (Cephfs) GetOrGrantAccess(ctx context.Context, args *GrantAccessArgs) (accessRight *shares.AccessRight, err error) {
36+
func (Cephfs) GetOrGrantAccesses(ctx context.Context, args *GrantAccessArgs) ([]shares.AccessRight, error) {
3637
// First, check if the access right exists or needs to be created
3738

38-
var rights []shares.AccessRight
39-
40-
accessTo := args.Options.CephfsClientID
41-
if accessTo == "" {
42-
accessTo = args.Share.Name
43-
}
44-
45-
rights, err = args.ManilaClient.GetAccessRights(ctx, args.Share.ID)
39+
rights, err := args.ManilaClient.GetAccessRights(ctx, args.Share.ID)
4640
if err != nil {
4741
if _, ok := err.(gophercloud.ErrResourceNotFound); !ok {
4842
return nil, fmt.Errorf("failed to list access rights: %v", err)
4943
}
50-
} else {
51-
// Try to find the access right
44+
}
45+
46+
accessToList := []string{args.Share.Name}
47+
if args.Options.CephfsClientID != "" {
48+
accessToList = strings.Split(args.Options.CephfsClientID, ",")
49+
}
5250

51+
created := false
52+
for _, at := range accessToList {
53+
// Try to find the access right
54+
found := false
5355
for _, r := range rights {
54-
if r.AccessTo == accessTo && r.AccessType == "cephx" && r.AccessLevel == "rw" {
56+
if r.AccessTo == at && r.AccessType == "cephx" && r.AccessLevel == "rw" {
5557
klog.V(4).Infof("cephx access right for share %s already exists", args.Share.Name)
56-
57-
accessRight = &r
58+
found = true
5859
break
5960
}
6061
}
61-
}
6262

63-
if accessRight == nil {
6463
// Not found, create it
65-
66-
accessRight, err = args.ManilaClient.GrantAccess(ctx, args.Share.ID, shares.GrantAccessOpts{
67-
AccessType: "cephx",
68-
AccessLevel: "rw",
69-
AccessTo: accessTo,
70-
})
71-
72-
if err != nil {
73-
return
64+
if !found {
65+
result, err := args.ManilaClient.GrantAccess(ctx, args.Share.ID, shares.GrantAccessOpts{
66+
AccessType: "cephx",
67+
AccessLevel: "rw",
68+
AccessTo: at,
69+
})
70+
if err != nil {
71+
return nil, fmt.Errorf("failed to grant access right: %v", err)
72+
}
73+
if result.AccessKey == "" {
74+
// Wait till a ceph key is assigned to the access right
75+
backoff := wait.Backoff{
76+
Duration: time.Second * 5,
77+
Factor: 1.2,
78+
Steps: 10,
79+
}
80+
wait_err := wait.ExponentialBackoff(backoff, func() (bool, error) {
81+
rights, err := args.ManilaClient.GetAccessRights(ctx, args.Share.ID)
82+
if err != nil {
83+
return false, fmt.Errorf("error get access rights for share %s: %v", args.Share.ID, err)
84+
}
85+
if len(rights) == 0 {
86+
return false, fmt.Errorf("cannot find the access right we've just created")
87+
}
88+
for _, r := range rights {
89+
if r.AccessTo == at && r.AccessKey != "" {
90+
return true, nil
91+
}
92+
}
93+
klog.V(4).Infof("Access key for %s is not set yet, retrying...", at)
94+
return false, nil
95+
})
96+
if wait_err != nil {
97+
return nil, fmt.Errorf("Timed out while attempting to get access rights for share %s: %v", args.Share.ID, err)
98+
}
99+
}
100+
created = true
74101
}
75102
}
76103

77-
if accessRight.AccessKey != "" {
78-
// The access right is ready
79-
return
80-
}
81-
82-
// Wait till a ceph key is assigned to the access right
83-
84-
backoff := wait.Backoff{
85-
Duration: time.Second * 5,
86-
Factor: 1.2,
87-
Steps: 10,
88-
}
89-
90-
return accessRight, wait.ExponentialBackoff(backoff, func() (bool, error) {
91-
rights, err := args.ManilaClient.GetAccessRights(ctx, args.Share.ID)
104+
// Search again because access rights have changed
105+
if created {
106+
rights, err = args.ManilaClient.GetAccessRights(ctx, args.Share.ID)
92107
if err != nil {
93-
return false, err
94-
}
95-
96-
var accessRight *shares.AccessRight
97-
98-
for i := range rights {
99-
if rights[i].AccessTo == accessTo {
100-
accessRight = &rights[i]
101-
break
108+
if _, ok := err.(gophercloud.ErrResourceNotFound); !ok {
109+
return nil, fmt.Errorf("failed to list access rights: %v", err)
102110
}
103111
}
104-
105-
if accessRight == nil {
106-
return false, fmt.Errorf("cannot find the access right we've just created")
107-
}
108-
109-
return accessRight.AccessKey != "", nil
110-
})
112+
}
113+
return rights, nil
111114
}
112115

113116
func (Cephfs) BuildVolumeContext(args *VolumeContextArgs) (volumeContext map[string]string, err error) {

pkg/csi/manila/shareadapters/nfs.go

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type NFS struct{}
3333

3434
var _ ShareAdapter = &NFS{}
3535

36-
func (NFS) GetOrGrantAccess(ctx context.Context, args *GrantAccessArgs) (*shares.AccessRight, error) {
36+
func (NFS) GetOrGrantAccesses(ctx context.Context, args *GrantAccessArgs) ([]shares.AccessRight, error) {
3737
// First, check if the access right exists or needs to be created
3838

3939
rights, err := args.ManilaClient.GetAccessRights(ctx, args.Share.ID)
@@ -43,22 +43,43 @@ func (NFS) GetOrGrantAccess(ctx context.Context, args *GrantAccessArgs) (*shares
4343
}
4444
}
4545

46-
// Try to find the access right
47-
48-
for _, r := range rights {
49-
if r.AccessTo == args.Options.NFSShareClient && r.AccessType == "ip" && r.AccessLevel == "rw" {
50-
klog.V(4).Infof("IP access right for share %s already exists", args.Share.Name)
51-
return &r, nil
46+
accessToList := strings.Split(args.Options.NFSShareClient, ",")
47+
48+
created := false
49+
for _, at := range accessToList {
50+
// Try to find the access right
51+
found := false
52+
for _, r := range rights {
53+
if r.AccessTo == at && r.AccessType == "ip" && r.AccessLevel == "rw" {
54+
klog.V(4).Infof("IP access right %s for share %s already exists", at, args.Share.Name)
55+
found = true
56+
break
57+
}
58+
}
59+
// Not found, create it
60+
if !found {
61+
_, err = args.ManilaClient.GrantAccess(ctx, args.Share.ID, shares.GrantAccessOpts{
62+
AccessType: "ip",
63+
AccessLevel: "rw",
64+
AccessTo: at,
65+
})
66+
if err != nil {
67+
return nil, fmt.Errorf("failed to grant access right: %v", err)
68+
}
69+
created = true
5270
}
5371
}
5472

55-
// Not found, create it
56-
57-
return args.ManilaClient.GrantAccess(ctx, args.Share.ID, shares.GrantAccessOpts{
58-
AccessType: "ip",
59-
AccessLevel: "rw",
60-
AccessTo: args.Options.NFSShareClient,
61-
})
73+
// Search again because access rights have changed
74+
if created {
75+
rights, err = args.ManilaClient.GetAccessRights(ctx, args.Share.ID)
76+
if err != nil {
77+
if _, ok := err.(gophercloud.ErrResourceNotFound); !ok {
78+
return nil, fmt.Errorf("failed to list access rights: %v", err)
79+
}
80+
}
81+
}
82+
return rights, nil
6283
}
6384

6485
func (NFS) BuildVolumeContext(args *VolumeContextArgs) (volumeContext map[string]string, err error) {

pkg/csi/manila/shareadapters/shareadapter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type ShareAdapter interface {
4646
// GetOrGrantAccess first tries to retrieve an access right for args.Share.
4747
// An access right is created for the share in case it doesn't exist yet.
4848
// Returns an existing or new access right for args.Share.
49-
GetOrGrantAccess(ctx context.Context, args *GrantAccessArgs) (accessRight *shares.AccessRight, err error)
49+
GetOrGrantAccesses(ctx context.Context, args *GrantAccessArgs) (accessRights []shares.AccessRight, err error)
5050

5151
// BuildVolumeContext builds a volume context map that's passed to NodeStageVolumeRequest and NodePublishVolumeRequest
5252
BuildVolumeContext(args *VolumeContextArgs) (volumeContext map[string]string, err error)

tests/e2e/csi/manila/testdriver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,8 @@ func (d *manilaTestDriver) GetPersistentVolumeSource(readOnly bool, fsType strin
197197
ReadOnly: readOnly,
198198
FSType: fsType,
199199
VolumeAttributes: map[string]string{
200-
"shareID": v.shareID,
201-
"shareAccessID": v.accessID,
200+
"shareID": v.shareID,
201+
"shareAccessIDs": v.accessID,
202202
},
203203
NodeStageSecretRef: &v1.SecretReference{
204204
Name: manilaSecretName,

0 commit comments

Comments
 (0)