Skip to content
Open
Show file tree
Hide file tree
Changes from 11 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
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ services: docker
dist: focal
language: go
go:
- 1.23.x
- 1.24.x

env:
global:
Expand Down Expand Up @@ -54,7 +54,7 @@ env:

# Build tool versions
- KUSTOMIZE_VERSION=4.5.2
- GOLANGCI_LINT_VERSION=v1.59.0
- GOLANGCI_LINT_VERSION=v1.64.8

# Operator ENV
- OCTOKIT_API_ENDPOINT="https://github.ibm.com/api/v3/"
Expand Down Expand Up @@ -121,7 +121,7 @@ jobs:
- curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash -s -- $KUSTOMIZE_VERSION ${HOME}/bin
# Testing that the generated files match the deploy/*.yaml files, it they do not match, fail Travis
- ansible-playbook ${TRAVIS_BUILD_DIR}/tools/ansible/generate-playbook.yaml --extra-vars "travis_testing=true"
- golangci-lint run --no-config --disable-all -E gosec --out-format json,colored-line-number --timeout 3m0s
- golangci-lint run --no-config --disable-all -E gosec --out-format json,colored-line-number --timeout 10m0s

- stage: build
name: "Build - Driver: image and push to registry"
Expand Down
2 changes: 1 addition & 1 deletion driver/build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Multi-arch build for IBM Storage Scale CSI Driver
# usage: docker buildx build -f build/multi-arch.Dockerfile --platform=linux/amd64 -t my_image_tag .

FROM --platform=$BUILDPLATFORM golang:1.23 AS builder
FROM --platform=$BUILDPLATFORM golang:1.24 AS builder
WORKDIR /go/src/github.com/IBM/ibm-spectrum-scale-csi/driver/
COPY ./go.mod .
COPY ./go.sum .
Expand Down
27 changes: 15 additions & 12 deletions driver/csiplugin/controllerserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
"k8s.io/klog/v2"
)
Expand Down Expand Up @@ -230,6 +231,7 @@ func (cs *ScaleControllerServer) createDirectory(ctx context.Context, scVol *sca
return nil
}

/*
// createSoftlink: Create soft link if not present
func (cs *ScaleControllerServer) createSoftlink(ctx context.Context, scVol *scaleVolume, target string) error {
loggerId := utils.GetLoggerId(ctx)
Expand All @@ -250,7 +252,7 @@ func (cs *ScaleControllerServer) createSoftlink(ctx context.Context, scVol *scal
}
}
return nil
}
} */

// setQuota: Set quota if not set
func (cs *ScaleControllerServer) setQuota(ctx context.Context, scVol *scaleVolume, volName string) error {
Expand Down Expand Up @@ -857,9 +859,9 @@ func (cs *ScaleControllerServer) CreateVolume(newctx context.Context, req *csi.C
ctx := utils.SetModuleName(newctx, createVolume)

// Mask the secrets from request before logging
reqToLog := *req
reqToLog := proto.Clone(req).(*csi.CreateVolumeRequest)
reqToLog.Secrets = nil
klog.Infof("[%s] CreateVolume req: %v", loggerId, &reqToLog)
klog.Infof("[%s] CreateVolume req: %+v", loggerId, reqToLog)

if err := cs.Driver.ValidateControllerServiceRequest(ctx, csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
klog.Errorf("[%s] invalid create volume req: %v", loggerId, req)
Expand Down Expand Up @@ -972,10 +974,11 @@ func (cs *ScaleControllerServer) CreateVolume(newctx context.Context, req *csi.C
}
} else {
if scaleVol.VolumeType == cacheVolume {
if scaleVol.CacheMode == "" {
switch scaleVol.CacheMode {
case "":
// cacheMode is not specified, use AFM mode IW by default for other volume access modes
scaleVol.CacheMode = afmModeIW
} else if scaleVol.CacheMode == afmModeRO {
case afmModeRO:
return nil, status.Error(codes.InvalidArgument, "The cacheMode readonly is only supported with the volume access mode ReadOnlyMany")
}
}
Expand Down Expand Up @@ -1322,7 +1325,7 @@ func validateCacheSecret(ctx context.Context, secretData map[string]string) ([]s

if len(secretData) == 0 {
klog.Errorf("[%s] secret in the req doesn't have any parameters", loggerId)
return nil, false, status.Error(codes.Internal, fmt.Sprintf("secret in the req doesn't have any parameters"))
return nil, false, status.Error(codes.Internal, "secret in the req doesn't have any parameters")
}

if _, exists := secretData[KeysForNfs[0]]; exists {
Expand Down Expand Up @@ -2587,9 +2590,9 @@ func (cs *ScaleControllerServer) DeleteVolume(newctx context.Context, req *csi.D
ctx := utils.SetModuleName(newctx, deleteVolume)

// Mask the secrets from request before logging
reqToLog := *req
reqToLog := proto.Clone(req).(*csi.DeleteVolumeRequest)
reqToLog.Secrets = nil
klog.Infof("[%s] DeleteVolume req: %v", loggerId, &reqToLog)
klog.Infof("[%s] DeleteVolume req: %v", loggerId, reqToLog)

if err := cs.Driver.ValidateControllerServiceRequest(ctx, csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME); err != nil {
klog.Errorf("[%s] Invalid delete volume req: %v", loggerId, req)
Expand Down Expand Up @@ -2801,8 +2804,8 @@ func (cs *ScaleControllerServer) DeleteVolume(newctx context.Context, req *csi.D
if !isNfsSupported {
bucketName := req.Secrets[connectors.BucketName]
endpoint := req.Secrets[connectors.BucketEndpoint]
if err != nil {
return nil, fmt.Errorf("failed to parse endpoint URL %s, error %v", endpoint, err)
if endpoint == "" || bucketName == "" {
return nil, fmt.Errorf("failed to parse endpoint URL %s and bucket name %s, error %v", endpoint, bucketName, err)
}
err = conn.DeleteBucketKeys(ctx, bucketName+":"+volumeName+"-exportmap")
if err != nil {
Expand Down Expand Up @@ -3125,12 +3128,12 @@ func (cs *ScaleControllerServer) ControllerPublishVolume(ctx context.Context, re
//error when FS is not mounted on all the gatewayNodes for "cache" volume
if volumeIDMembers.StorageClassType == STORAGECLASS_CACHE && !isFsMountedOnGateway {
message := fmt.Sprintf("[%s] ControllerPublishVolume : filesystem %s is not mounted on all the gatewayNodes %v", loggerId, fsName, gatewayNodeNames)
klog.Errorf(message)
klog.Errorf("%s", message)
return nil, status.Error(codes.Internal, message)
}
if !isFsMounted {
message := fmt.Sprintf("[%s] ControllerPublishVolume : filesystem %s is not mounted on node %s", loggerId, fsName, scalenodeID)
klog.Errorf(message)
klog.Errorf("%s", message)
return nil, status.Error(codes.Internal, message)
}
}
Expand Down
4 changes: 2 additions & 2 deletions driver/csiplugin/gpfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ const (

// BLOCK_FILESET_VOLUME = 3

defaultPrimaryFileset = "spectrum-scale-csi-volume-store"
symlinkDir = ".volumes"
// defaultPrimaryFileset = "spectrum-scale-csi-volume-store"
// symlinkDir = ".volumes"
volumeStatsCapability = "VOLUME_STATS_CAPABILITY"
)

Expand Down
7 changes: 4 additions & 3 deletions driver/csiplugin/gpfs_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,16 @@ func getScaleVolumeOptions(ctx context.Context, volOptions map[string]string) (*
}

if fsetTypeSpecified {
if fsetType == dependentFileset {
switch fsetType {
case dependentFileset:
if inodeLimSpecified {
return &scaleVolume{}, status.Error(codes.InvalidArgument, "inodeLimit and filesetType=dependent must not be specified together in storageClass")
}
} else if fsetType == independentFileset {
case independentFileset:
if isparentFilesetSpecified {
return &scaleVolume{}, status.Error(codes.InvalidArgument, "parentFileset and filesetType=independent(Default) must not be specified together in storageClass")
}
} else {
default:
return &scaleVolume{}, status.Error(codes.InvalidArgument, "Invalid value specified for filesetType in storageClass")
}
}
Expand Down
150 changes: 76 additions & 74 deletions driver/csiplugin/parallelSnapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package scale
import (
"context"
"sync"

"github.com/IBM/ibm-spectrum-scale-csi/driver/csiplugin/utils"
"k8s.io/klog/v2"
)
Expand All @@ -22,105 +23,106 @@ var createSnapshotRefLock map[string]int
var cgSnapLock map[string]string
var cgSnapMutex sync.Mutex


func CgSnapshotLock(ctx context.Context, targetPath string, snapExists bool) bool {
cgSnapMutex.Lock()
defer cgSnapMutex.Unlock()
return cgParallelSnapshotLock(ctx,targetPath, snapExists )
return cgParallelSnapshotLock(ctx, targetPath, snapExists)
}

func cgParallelSnapshotLock(ctx context.Context, targetPath string, snapExists bool) bool {

if len(createVolumeRefLock) == 0 {
createVolumeRefLock = make(map[string]int)
}

if len(createSnapshotRefLock) == 0 {
createSnapshotRefLock = make(map[string]int)
}

if len(cgSnapLock) == 0 {
cgSnapLock = make(map[string]string)
}

lockingModule := utils.GetModuleName(ctx)

createVolCount, _ := createVolumeRefLock[targetPath]
createSnapCount, _ := createSnapshotRefLock[targetPath]
moduleName, exists := cgSnapLock[targetPath]
if createVolCount > 0 || createSnapCount > 0 {
if lockingModule == createVolume {
createVolumeRefLock[targetPath]++
cgSnapLock[targetPath] = lockingModule
return true
} else if lockingModule == createSnapshot {
if !snapExists {
if len(createVolumeRefLock) == 0 {
createVolumeRefLock = make(map[string]int)
}

if len(createSnapshotRefLock) == 0 {
createSnapshotRefLock = make(map[string]int)
}

if len(cgSnapLock) == 0 {
cgSnapLock = make(map[string]string)
}

lockingModule := utils.GetModuleName(ctx)

createVolCount, _ := createVolumeRefLock[targetPath]
createSnapCount, _ := createSnapshotRefLock[targetPath]
moduleName, exists := cgSnapLock[targetPath]
if createVolCount > 0 || createSnapCount > 0 {
switch lockingModule {
case createVolume:
createVolumeRefLock[targetPath]++
cgSnapLock[targetPath] = lockingModule
return true
case createSnapshot:
if !snapExists {
if createSnapCount > 0 {
klog.Infof("[%s] Snap doesn't exist and lock already acquired by another snapshot request", utils.GetLoggerId(ctx))
return false
} else{
} else {
createSnapshotRefLock[targetPath] = createOpInitCount
cgSnapLock[targetPath] = lockingModule
return true
}
} else {
createSnapshotRefLock[targetPath]++
cgSnapLock[targetPath] = lockingModule
return true
}
} else {
klog.Infof("[%s] Delete operation is trying to acquire lock while create action is in progress", utils.GetLoggerId(ctx))
} else {
createSnapshotRefLock[targetPath]++
cgSnapLock[targetPath] = lockingModule
return true
}
default:
klog.Infof("[%s] Delete operation is trying to acquire lock while create action is in progress", utils.GetLoggerId(ctx))
return false
}
} else {
if exists && moduleName != "" {
if (moduleName == deleteVolume || moduleName == deleteSnapshot) && (lockingModule == createVolume || lockingModule == createSnapshot) {
klog.Infof("[%s] Delete operation acquired the lock, create operation retrying", utils.GetLoggerId(ctx))
}
} else {
if exists && moduleName != "" {
if (moduleName == deleteVolume || moduleName == deleteSnapshot) && (lockingModule == createVolume || lockingModule == createSnapshot) {
klog.Infof("[%s] Delete operation acquired the lock, create operation retrying", utils.GetLoggerId(ctx))
return false
}
} else {
if lockingModule == createVolume {
createVolumeRefLock[targetPath] = createOpInitCount
} else if lockingModule == createSnapshot {
createSnapshotRefLock[targetPath] = createOpInitCount
} else {
klog.Infof("[%s] Delete operation acquired the lock", utils.GetLoggerId(ctx))
}
}
cgSnapLock[targetPath] = lockingModule
}

klog.V(4).Infof("[%s] The target path is locked for %s: [%s]", utils.GetLoggerId(ctx), utils.GetModuleName(ctx), targetPath)
return true
}
} else {
switch lockingModule {
case createVolume:
createVolumeRefLock[targetPath] = createOpInitCount
case createSnapshot:
createSnapshotRefLock[targetPath] = createOpInitCount
default:
klog.Infof("[%s] Delete operation acquired the lock", utils.GetLoggerId(ctx))
}
}
cgSnapLock[targetPath] = lockingModule
}

klog.V(4).Infof("[%s] The target path is locked for %s: [%s]", utils.GetLoggerId(ctx), utils.GetModuleName(ctx), targetPath)
return true
}


func CgSnapshotUnlock(ctx context.Context, targetPath string) {
cgSnapMutex.Lock()
defer cgSnapMutex.Unlock()
cgParallelSnapshotUnlock(ctx, targetPath)
cgParallelSnapshotUnlock(ctx, targetPath)
}

func cgParallelSnapshotUnlock(ctx context.Context, targetPath string) {
moduleName := utils.GetModuleName(ctx)
if moduleName == createVolume {
if createVolumeRefLock[targetPath] > 0 {
createVolumeRefLock[targetPath]--
} else {
delete(createVolumeRefLock, targetPath)
}
} else if moduleName == createSnapshot {
if createSnapshotRefLock[targetPath] > 0 {
moduleName := utils.GetModuleName(ctx)
switch moduleName {
case createVolume:
if createVolumeRefLock[targetPath] > 0 {
createVolumeRefLock[targetPath]--
} else {
delete(createVolumeRefLock, targetPath)
}
case createSnapshot:
if createSnapshotRefLock[targetPath] > 0 {
klog.Infof("[%s] Decrease the count of createSnapshotRefLock", utils.GetLoggerId(ctx))
createSnapshotRefLock[targetPath]--
} else {
delete(createSnapshotRefLock, targetPath)
}
} else {
klog.Infof("[%s] Delete operation released the lock", utils.GetLoggerId(ctx))
}
delete(cgSnapLock, targetPath)
klog.Infof("[%s] The target path is unlocked for %s: [%s]", utils.GetLoggerId(ctx), utils.GetModuleName(ctx), targetPath)
createSnapshotRefLock[targetPath]--
} else {
delete(createSnapshotRefLock, targetPath)
}
default:
klog.Infof("[%s] Delete operation released the lock", utils.GetLoggerId(ctx))
}
delete(cgSnapLock, targetPath)
klog.Infof("[%s] The target path is unlocked for %s: [%s]", utils.GetLoggerId(ctx), utils.GetModuleName(ctx), targetPath)
}

/*func retrySnapLock(ctx context.Context, targetPath, lockingModule string, snapExists bool) error {
Expand Down
7 changes: 4 additions & 3 deletions driver/csiplugin/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,15 @@ func (s *nonBlockingGRPCServer) serve(endpoint string, ids csi.IdentityServer, c
}

var addr string
if u.Scheme == "unix" {
switch u.Scheme {
case "unix":
addr = u.Path
if err := os.Remove(addr); err != nil && !os.IsNotExist(err) {
klog.Fatalf("Failed to remove %s, error: %s", addr, err.Error())
}
} else if u.Scheme == "tcp" {
case "tcp":
addr = u.Host
} else {
default:
klog.Fatalf("%v endpoint scheme not supported", u.Scheme)
}

Expand Down
Loading