Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[manila-csi-plugin] support muilple share rules #2727

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions pkg/csi/manila/controllerserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,18 +193,24 @@ func (cs *controllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol

ad := getShareAdapter(shareOpts.Protocol)

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

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

var accessRightIDs []string
for _, ar := range accessRights {
accessRightIDs = append(accessRightIDs, ar.ID)
}
shareAccessIDs := strings.Join(accessRightIDs, ",")

volCtx := filterParametersForVolumeContext(params, options.NodeVolumeContextFields())
volCtx = util.SetMapIfNotEmpty(volCtx, "shareID", share.ID)
volCtx = util.SetMapIfNotEmpty(volCtx, "shareAccessID", accessRight.ID)
volCtx = util.SetMapIfNotEmpty(volCtx, "shareAccessIDs", shareAccessIDs)
volCtx = util.SetMapIfNotEmpty(volCtx, "groupID", share.ShareGroupID)
volCtx = util.SetMapIfNotEmpty(volCtx, "affinity", shareOpts.Affinity)
volCtx = util.SetMapIfNotEmpty(volCtx, "antiAffinity", shareOpts.AntiAffinity)
Expand Down
112 changes: 56 additions & 56 deletions pkg/csi/manila/shareadapters/cephfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package shareadapters

import (
"fmt"
"strings"
"time"

"github.com/gophercloud/gophercloud/v2"
Expand All @@ -31,82 +32,81 @@ type Cephfs struct{}

var _ ShareAdapter = &Cephfs{}

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

var rights []shares.AccessRight

accessTo := args.Options.CephfsClientID
if accessTo == "" {
accessTo = args.Share.Name
}

rights, err = args.ManilaClient.GetAccessRights(args.Share.ID)
rights, err := args.ManilaClient.GetAccessRights(args.Share.ID)
if err != nil {
if _, ok := err.(gophercloud.ErrResourceNotFound); !ok {
return nil, fmt.Errorf("failed to list access rights: %v", err)
}
} else {
// Try to find the access right
}

accessToList := []string{args.Share.Name}
if args.Options.CephfsClientID != "" {
accessToList = strings.Split(args.Options.CephfsClientID, ",")
}

created := false
for _, at := range accessToList {
// Try to find the access right
found := false
for _, r := range rights {
if r.AccessTo == accessTo && r.AccessType == "cephx" && r.AccessLevel == "rw" {
if r.AccessTo == at && r.AccessType == "cephx" && r.AccessLevel == "rw" {
klog.V(4).Infof("cephx access right for share %s already exists", args.Share.Name)

accessRight = &r
found = true
break
}
}
}

if accessRight == nil {
// Not found, create it

accessRight, err = args.ManilaClient.GrantAccess(args.Share.ID, shares.GrantAccessOpts{
AccessType: "cephx",
AccessLevel: "rw",
AccessTo: accessTo,
})

if err != nil {
return
if !found {
result, err := args.ManilaClient.GrantAccess(args.Share.ID, shares.GrantAccessOpts{
AccessType: "cephx",
AccessLevel: "rw",
AccessTo: at,
})
if err != nil {
return nil, fmt.Errorf("failed to grant access right: %v", err)
}
if result.AccessKey == "" {
// Wait till a ceph key is assigned to the access right
backoff := wait.Backoff{
Duration: time.Second * 5,
Factor: 1.2,
Steps: 10,
}
wait.ExponentialBackoff(backoff, func() (bool, error) {
rights, err := args.ManilaClient.GetAccessRights(args.Share.ID)
if err != nil {
return false, fmt.Errorf("error get access rights for share %s: %v", args.Share.ID, err)
}
if len(rights) == 0 {
return false, fmt.Errorf("cannot find the access right we've just created")
}
for _, r := range rights {
if r.AccessTo == at && r.AccessKey != "" {
return true, nil
}
}
klog.V(4).Infof("Access key for %s is not set yet, retrying...", at)
return false, nil
})
}
created = true
}
}

if accessRight.AccessKey != "" {
// The access right is ready
return
}

// Wait till a ceph key is assigned to the access right

backoff := wait.Backoff{
Duration: time.Second * 5,
Factor: 1.2,
Steps: 10,
}

return accessRight, wait.ExponentialBackoff(backoff, func() (bool, error) {
rights, err := args.ManilaClient.GetAccessRights(args.Share.ID)
// Search again because access rights have changed
if created {
rights, err = args.ManilaClient.GetAccessRights(args.Share.ID)
if err != nil {
return false, err
}

var accessRight *shares.AccessRight

for i := range rights {
if rights[i].AccessTo == accessTo {
accessRight = &rights[i]
break
if _, ok := err.(gophercloud.ErrResourceNotFound); !ok {
return nil, fmt.Errorf("failed to list access rights: %v", err)
}
}

if accessRight == nil {
return false, fmt.Errorf("cannot find the access right we've just created")
}

return accessRight.AccessKey != "", nil
})
}
return rights, nil
}

func (Cephfs) BuildVolumeContext(args *VolumeContextArgs) (volumeContext map[string]string, err error) {
Expand Down
49 changes: 35 additions & 14 deletions pkg/csi/manila/shareadapters/nfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type NFS struct{}

var _ ShareAdapter = &NFS{}

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

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

// Try to find the access right

for _, r := range rights {
if r.AccessTo == args.Options.NFSShareClient && r.AccessType == "ip" && r.AccessLevel == "rw" {
klog.V(4).Infof("IP access right for share %s already exists", args.Share.Name)
return &r, nil
accessToList := strings.Split(args.Options.NFSShareClient, ",")

created := false
for _, at := range accessToList {
// Try to find the access right
found := false
for _, r := range rights {
if r.AccessTo == at && r.AccessType == "ip" && r.AccessLevel == "rw" {
klog.V(4).Infof("IP access right %s for share %s already exists", at, args.Share.Name)
found = true
break
}
}
// Not found, create it
if !found {
_, err = args.ManilaClient.GrantAccess(args.Share.ID, shares.GrantAccessOpts{
AccessType: "ip",
AccessLevel: "rw",
AccessTo: at,
})
if err != nil {
return nil, fmt.Errorf("failed to grant access right: %v", err)
}
created = true
}
}

// Not found, create it

return args.ManilaClient.GrantAccess(args.Share.ID, shares.GrantAccessOpts{
AccessType: "ip",
AccessLevel: "rw",
AccessTo: args.Options.NFSShareClient,
})
// Search again because access rights have changed
if created {
rights, err = args.ManilaClient.GetAccessRights(args.Share.ID)
if err != nil {
if _, ok := err.(gophercloud.ErrResourceNotFound); !ok {
return nil, fmt.Errorf("failed to list access rights: %v", err)
}
}
}
return rights, nil
}

func (NFS) BuildVolumeContext(args *VolumeContextArgs) (volumeContext map[string]string, err error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/csi/manila/shareadapters/shareadapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type ShareAdapter interface {
// GetOrGrantAccess first tries to retrieve an access right for args.Share.
// An access right is created for the share in case it doesn't exist yet.
// Returns an existing or new access right for args.Share.
GetOrGrantAccess(args *GrantAccessArgs) (accessRight *shares.AccessRight, err error)
GetOrGrantAccesses(args *GrantAccessArgs) (accessRights []shares.AccessRight, err error)

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