mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
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:
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
|
73
internal/rbd/group/util_test.go
Normal file
73
internal/rbd/group/util_test.go
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Reference in New Issue
Block a user