cleanup: move internal/rbd/errors.go to internal/rbd/errors pacakge

Signed-off-by: Praveen M <m.praveen@ibm.com>
(cherry picked from commit 5cbc14454a)

# Conflicts:
#	internal/csi-addons/rbd/encryptionkeyrotation.go
#	internal/csi-addons/rbd/reclaimspace.go
#	internal/csi-addons/rbd/replication.go
#	internal/csi-addons/rbd/replication_test.go
#	internal/rbd/clone.go
#	internal/rbd/controllerserver.go
#	internal/rbd/group/util.go
#	internal/rbd/group/util_test.go
#	internal/rbd/manager.go
#	internal/rbd/rbd_journal.go
#	internal/rbd/rbd_util.go
#	internal/rbd/rbd_util_test.go
#	internal/rbd/snapshot.go
#	internal/util/errors.go
This commit is contained in:
Praveen M
2025-03-03 11:45:43 +05:30
committed by Mergify
parent 7cff156d9a
commit 4dcb9d3a45
24 changed files with 632 additions and 63 deletions

View File

@ -24,6 +24,7 @@ import (
"github.com/container-storage-interface/spec/lib/go/csi"
"google.golang.org/protobuf/types/known/timestamppb"
rbderrors "github.com/ceph/ceph-csi/internal/rbd/errors"
"github.com/ceph/ceph-csi/internal/rbd/types"
"github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log"
@ -70,7 +71,7 @@ func GetVolumeGroupSnapshot(
attrs, err := vgs.getVolumeGroupAttributes(ctx)
if err != nil {
if errors.Is(err, ErrRBDGroupNotFound) {
if errors.Is(err, rbderrors.ErrGroupNotFound) {
log.ErrorLog(ctx, "%v, returning empty volume group snapshot %q", vgs, err)
return vgs, err

View File

@ -25,6 +25,7 @@ import (
"github.com/ceph/go-ceph/rados"
"github.com/ceph/ceph-csi/internal/journal"
rbderrors "github.com/ceph/ceph-csi/internal/rbd/errors"
"github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log"
)
@ -87,7 +88,82 @@ func (cvg *commonVolumeGroup) initCommonVolumeGroup(
pool, err := util.GetPoolName(mons, creds, csiID.LocationID)
if err != nil {
<<<<<<< HEAD
return fmt.Errorf("failed to get pool for volume group id %q: %w", id, err)
=======
return fmt.Errorf("failed to get pool for volume group id %q: %w", cvg.id, err)
}
cvg.monitors = mons
cvg.namespace = namespace
cvg.pool = pool
return nil
}
// generateVolumeGroupFromMapping checks the clusterID and poolID mapping and
// generates commonVolumeGroup structure for the mapped clusterID and poolID.
func (cvg *commonVolumeGroup) generateVolumeGroupFromMapping(
ctx context.Context,
csiID util.CSIIdentifier,
mapping *[]util.ClusterMappingInfo,
) error {
mcsiID := csiID
existingClusterID := csiID.ClusterID
existingPoolID := strconv.FormatInt(csiID.LocationID, 10)
for _, cm := range *mapping {
for key, val := range cm.ClusterIDMapping {
mappedClusterID := util.GetMappedID(key, val, csiID.ClusterID)
if mappedClusterID == "" {
continue
}
log.DebugLog(ctx,
"found new clusterID mapping %s for existing clusterID %s", mappedClusterID, existingClusterID)
// Add mapped clusterID to Identifier
mcsiID.ClusterID = mappedClusterID
for _, pools := range cm.RBDpoolIDMappingInfo {
for key, val := range pools {
mappedPoolID := util.GetMappedID(key, val, existingPoolID)
if mappedPoolID == "" {
continue
}
log.DebugLog(ctx,
"found new poolID mapping %s for existing poolID %s", mappedPoolID, existingPoolID)
mPID, err := strconv.ParseInt(mappedPoolID, 10, 64)
if err != nil {
return err
}
mcsiID.LocationID = mPID
err = cvg.generateVolumeGroup(mcsiID)
if ShouldRetryVolumeGroupGeneration(err) {
continue
}
return err
}
}
}
}
return util.ErrPoolNotFound
}
func (cvg *commonVolumeGroup) initCommonVolumeGroup(
ctx context.Context,
id string,
csiDriver string,
creds *util.Credentials,
) error {
csiID := util.CSIIdentifier{}
err := csiID.DecomposeCSIID(id)
if err != nil {
return fmt.Errorf("failed to decompose volume group id %q: %w", id, err)
>>>>>>> 5cbc1445 (cleanup: move internal/rbd/errors.go to internal/rbd/errors pacakge)
}
cvg.csiDriver = csiDriver
@ -95,9 +171,34 @@ func (cvg *commonVolumeGroup) initCommonVolumeGroup(
cvg.id = id
cvg.clusterID = csiID.ClusterID
cvg.objectUUID = csiID.ObjectUUID
<<<<<<< HEAD
cvg.monitors = mons
cvg.pool = pool
cvg.namespace = namespace
=======
// cvg.monitors, cvg.namespace, cvg.pool are set in generateVolumeGroup
err = cvg.generateVolumeGroup(csiID)
// If the error is not a retryable error, return from here.
if err != nil && !ShouldRetryVolumeGroupGeneration(err) {
return err
}
// If the error is a retryable error, we should try to get the cluster mapping
// and generate the volume group from the mapping.
if ShouldRetryVolumeGroupGeneration(err) {
mapping, err := util.GetClusterMappingInfo(csiID.ClusterID)
if err != nil {
return err
}
if mapping != nil {
err = cvg.generateVolumeGroupFromMapping(ctx, csiID, mapping)
if err != nil {
return err
}
}
}
>>>>>>> 5cbc1445 (cleanup: move internal/rbd/errors.go to internal/rbd/errors pacakge)
log.DebugLog(ctx, "object for volume group %q has been initialized", cvg.id)
@ -148,7 +249,7 @@ func (cvg *commonVolumeGroup) getVolumeGroupAttributes(ctx context.Context) (*jo
if attrs.GroupName == "" {
log.ErrorLog(ctx, "volume group with id %v not found", cvg.id)
return nil, ErrRBDGroupNotFound
return nil, rbderrors.ErrGroupNotFound
}
cvg.requestName = attrs.RequestName
@ -275,12 +376,12 @@ func (cvg *commonVolumeGroup) GetIOContext(ctx context.Context) (*rados.IOContex
conn, err := cvg.getConnection(ctx)
if err != nil {
return nil, fmt.Errorf("%w: failed to connect: %w", ErrRBDGroupNotConnected, err)
return nil, fmt.Errorf("%w: failed to connect: %w", rbderrors.ErrGroupNotConnected, err)
}
ioctx, err := conn.GetIoctx(cvg.pool)
if err != nil {
return nil, fmt.Errorf("%w: failed to get IOContext: %w", ErrRBDGroupNotConnected, err)
return nil, fmt.Errorf("%w: failed to get IOContext: %w", rbderrors.ErrGroupNotConnected, err)
}
if cvg.namespace != "" {
@ -336,3 +437,28 @@ func (cvg *commonVolumeGroup) GetCreationTime(ctx context.Context) (*time.Time,
return cvg.creationTime, nil
}
// ShouldRetryVolumeGroupGeneration determines whether the process of finding or generating
// volumegroups should continue based on the type of error encountered.
//
// It checks if the given error matches any of the following known errors:
// - ErrPoolNotFound: The rbd pool where the volumegroup/omap is expected doesn't exist.
// - ErrRBDGroupNotFound: The volumegroup doesn't exist in the rbd pool.
// - rados.ErrPermissionDenied: Permissions to access the pool is denied.
//
// If any of these errors are encountered, the function returns `true`, indicating
// that the volumegroup search should continue because of known error. Otherwise, it
// returns `false`, meaning the search should stop.
//
// This helper function is used in scenarios where multiple attempts may be made
// to retrieve or generate volumegroup information, and we want to gracefully handle
// specific failure cases while retrying for others.
func ShouldRetryVolumeGroupGeneration(err error) bool {
if err == nil {
return false // No error, do not retry
}
// Continue searching for specific known errors
return (errors.Is(err, util.ErrPoolNotFound) ||
errors.Is(err, rbderrors.ErrGroupNotFound) ||
errors.Is(err, rados.ErrPermissionDenied))
}

View File

@ -0,0 +1,73 @@
/*
Copyright 2025 The Ceph-CSI Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package group
import (
"errors"
"testing"
rbderrors "github.com/ceph/ceph-csi/internal/rbd/errors"
"github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/go-ceph/rados"
)
func Test_shouldRetryVolumeGroupGeneration(t *testing.T) {
t.Parallel()
type args struct {
err error
}
tests := []struct {
name string
args args
want bool
}{
{
name: "No error (stop searching)",
args: args{err: nil},
want: false, // No error, stop searching
},
{
name: "ErrPoolNotFound (continue searching)",
args: args{err: util.ErrPoolNotFound},
want: true, // Known error, continue searching
},
{
name: "ErrRBDGroupNotFound (continue searching)",
args: args{err: rbderrors.ErrGroupNotFound},
want: true, // Known error, continue searching
},
{
name: "ErrPermissionDenied (continue searching)",
args: args{err: rados.ErrPermissionDenied},
want: true, // Known error, continue searching
},
{
name: "Different error (stop searching)",
args: args{err: errors.New("unknown error")},
want: false, // Unknown error, stop searching
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := ShouldRetryVolumeGroupGeneration(tt.args.err); got != tt.want {
t.Errorf("ShouldRetryVolumeGeneration() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -22,21 +22,16 @@ import (
"fmt"
"github.com/ceph/go-ceph/rados"
librados "github.com/ceph/go-ceph/rados"
librbd "github.com/ceph/go-ceph/rbd"
"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/csi-addons/spec/lib/go/volumegroup"
rbderrors "github.com/ceph/ceph-csi/internal/rbd/errors"
"github.com/ceph/ceph-csi/internal/rbd/types"
"github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log"
)
var (
ErrRBDGroupNotConnected = fmt.Errorf("%w: RBD group is not connected", librados.ErrNotConnected)
ErrRBDGroupNotFound = fmt.Errorf("%w: RBD group not found", librbd.ErrNotFound)
)
// volumeGroup handles all requests for 'rbd group' operations.
type volumeGroup struct {
commonVolumeGroup
@ -77,7 +72,7 @@ func GetVolumeGroup(
attrs, err := vg.getVolumeGroupAttributes(ctx)
if err != nil {
if errors.Is(err, ErrRBDGroupNotFound) {
if errors.Is(err, rbderrors.ErrGroupNotFound) {
log.ErrorLog(ctx, "%v, returning empty volume group %q", vg, err)
return vg, err