rbd: set SnapshotGroupID on each Snapshot of a VolumeGroupSnapshot

Without the SnapshotGroupID in the Snapshot object, Kubernetes CSI does
not know that the Snapshot belongs to a group. In that case, it allows
the deletion of the Snapshot, which should be denied.

Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
Niels de Vos 2024-10-25 17:24:50 +02:00 committed by mergify[bot]
parent ec1e7a4ee0
commit cea8bf8110
5 changed files with 52 additions and 10 deletions

View File

@ -155,6 +155,12 @@ func NewVolumeGroupSnapshot(
} }
volumeMap[handle] = name volumeMap[handle] = name
// store the CSI ID of the group in the snapshot attributes
snapErr = snapshot.SetVolumeGroup(ctx, creds, vgs.id)
if snapErr != nil {
return nil, fmt.Errorf("failed to set volume group ID %q for snapshot %q: %w", vgs.id, name, snapErr)
}
} }
j, err := vgs.getJournal(ctx) j, err := vgs.getJournal(ctx)

View File

@ -212,11 +212,6 @@ func (mgr *rbdManager) GetSnapshotByID(ctx context.Context, id string) (types.Sn
} }
} }
// FIXME: The snapshot will have RbdImageName set to the image that was
// used as source. This is not correct for group snapshots images, and
// need to be fixed. See rbdVolume.NewSnapshotByID() for more details.
snapshot.RbdImageName = snapshot.RbdSnapName
return snapshot, nil return snapshot, nil
} }

View File

@ -191,6 +191,9 @@ type rbdSnapshot struct {
// RbdSnapName is the name of the RBD snapshot backing this rbdSnapshot // RbdSnapName is the name of the RBD snapshot backing this rbdSnapshot
SourceVolumeID string SourceVolumeID string
RbdSnapName string RbdSnapName string
// groupID is the CSI volume group ID where this snapshot belongs to
groupID string
} }
// imageFeature represents required image features and value. // imageFeature represents required image features and value.
@ -1054,6 +1057,15 @@ func genSnapFromSnapID(
} }
} }
if imageAttributes.GroupID != "" {
rbdSnap.groupID = imageAttributes.GroupID
// FIXME: The snapshot will have RbdImageName set to the image
// that was used as source. This is not correct for group
// snapshots images, and need to be fixed. See
// rbdVolume.NewSnapshotByID() for more details.
rbdSnap.RbdImageName = rbdSnap.RbdSnapName
}
err = rbdSnap.Connect(cr) err = rbdSnap.Connect(cr)
if err != nil { if err != nil {
return rbdSnap, fmt.Errorf("failed to connect to %q: %w", return rbdSnap, fmt.Errorf("failed to connect to %q: %w",

View File

@ -158,6 +158,7 @@ func (rbdSnap *rbdSnapshot) ToCSI(ctx context.Context) (*csi.Snapshot, error) {
SourceVolumeId: rbdSnap.SourceVolumeID, SourceVolumeId: rbdSnap.SourceVolumeID,
CreationTime: timestamppb.New(*created), CreationTime: timestamppb.New(*created),
ReadyToUse: true, ReadyToUse: true,
GroupSnapshotId: rbdSnap.groupID,
}, nil }, nil
} }
@ -315,3 +316,26 @@ func (rv *rbdVolume) NewSnapshotByID(
return snap, nil return snap, nil
} }
func (rbdSnap *rbdSnapshot) SetVolumeGroup(ctx context.Context, cr *util.Credentials, groupID string) error {
vi := util.CSIIdentifier{}
err := vi.DecomposeCSIID(rbdSnap.VolID)
if err != nil {
return err
}
j, err := snapJournal.Connect(rbdSnap.Monitors, rbdSnap.RadosNamespace, cr)
if err != nil {
return fmt.Errorf("snapshot %q failed to connect to journal: %w", rbdSnap, err)
}
defer j.Destroy()
err = j.StoreGroupID(ctx, rbdSnap.Pool, vi.ObjectUUID, groupID)
if err != nil {
return fmt.Errorf("failed to set volume group ID for snapshot %q: %w", rbdSnap, err)
}
rbdSnap.groupID = groupID
return nil
}

View File

@ -21,6 +21,8 @@ import (
"time" "time"
"github.com/container-storage-interface/spec/lib/go/csi" "github.com/container-storage-interface/spec/lib/go/csi"
"github.com/ceph/ceph-csi/internal/util"
) )
type Snapshot interface { type Snapshot interface {
@ -35,4 +37,7 @@ type Snapshot interface {
ToCSI(ctx context.Context) (*csi.Snapshot, error) ToCSI(ctx context.Context) (*csi.Snapshot, error)
GetCreationTime(ctx context.Context) (*time.Time, error) GetCreationTime(ctx context.Context) (*time.Time, error)
// SetVolumeGroup sets the CSI volume group ID in the snapshot.
SetVolumeGroup(ctx context.Context, creds *util.Credentials, vgID string) error
} }