Skip to content

Commit b5965eb

Browse files
committed
[manila-csi-plugin] support muilple share rules
Signed-off-by: moonek <[email protected]>
1 parent d3f9104 commit b5965eb

File tree

4 files changed

+107
-73
lines changed

4 files changed

+107
-73
lines changed

pkg/csi/manila/controllerserver.go

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

194194
ad := getShareAdapter(shareOpts.Protocol)
195195

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

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

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

pkg/csi/manila/shareadapters/cephfs.go

Lines changed: 62 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package shareadapters
1818

1919
import (
2020
"fmt"
21+
"strings"
2122
"time"
2223

2324
"github.com/gophercloud/gophercloud/v2"
@@ -31,82 +32,88 @@ type Cephfs struct{}
3132

3233
var _ ShareAdapter = &Cephfs{}
3334

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

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

52+
modified := false
53+
for _, at := range accessToList {
54+
// Try to find the access right
55+
found := false
5256
for _, r := range rights {
53-
if r.AccessTo == accessTo && r.AccessType == "cephx" && r.AccessLevel == "rw" {
57+
if r.AccessTo == at && r.AccessType == "cephx" && r.AccessLevel == "rw" {
5458
klog.V(4).Infof("cephx access right for share %s already exists", args.Share.Name)
55-
56-
accessRight = &r
59+
found = true
5760
break
5861
}
5962
}
60-
}
6163

62-
if accessRight == nil {
6364
// Not found, create it
64-
65-
accessRight, err = args.ManilaClient.GrantAccess(args.Share.ID, shares.GrantAccessOpts{
66-
AccessType: "cephx",
67-
AccessLevel: "rw",
68-
AccessTo: accessTo,
69-
})
70-
71-
if err != nil {
72-
return
65+
if !found {
66+
result, err := args.ManilaClient.GrantAccess(args.Share.ID, shares.GrantAccessOpts{
67+
AccessType: "cephx",
68+
AccessLevel: "rw",
69+
AccessTo: at,
70+
})
71+
if err != nil {
72+
return nil, fmt.Errorf("failed to grant access right: %v", err)
73+
}
74+
if result.AccessKey == "" {
75+
// Wait till a ceph key is assigned to the access right
76+
backoff := wait.Backoff{
77+
Duration: time.Second * 5,
78+
Factor: 1.2,
79+
Steps: 10,
80+
}
81+
wait.ExponentialBackoff(backoff, func() (bool, error) {
82+
rights, err := args.ManilaClient.GetAccessRights(args.Share.ID)
83+
if err != nil {
84+
return false, err
85+
}
86+
87+
var accessRight *shares.AccessRight
88+
89+
for i := range rights {
90+
if rights[i].AccessTo == at {
91+
accessRight = &rights[i]
92+
break
93+
}
94+
}
95+
96+
if accessRight == nil {
97+
return false, fmt.Errorf("cannot find the access right we've just created")
98+
}
99+
100+
return accessRight.AccessKey != "", nil
101+
})
102+
}
103+
modified = true
73104
}
74105
}
75106

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

112119
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
@@ -32,7 +32,7 @@ type NFS struct{}
3232

3333
var _ ShareAdapter = &NFS{}
3434

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

3838
rights, err := args.ManilaClient.GetAccessRights(args.Share.ID)
@@ -42,22 +42,43 @@ func (NFS) GetOrGrantAccess(args *GrantAccessArgs) (*shares.AccessRight, error)
4242
}
4343
}
4444

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

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

6384
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
@@ -44,7 +44,7 @@ type ShareAdapter interface {
4444
// GetOrGrantAccess first tries to retrieve an access right for args.Share.
4545
// An access right is created for the share in case it doesn't exist yet.
4646
// Returns an existing or new access right for args.Share.
47-
GetOrGrantAccess(args *GrantAccessArgs) (accessRight *shares.AccessRight, err error)
47+
GetOrGrantAccesses(args *GrantAccessArgs) (accessRights []shares.AccessRight, err error)
4848

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

0 commit comments

Comments
 (0)