mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-18 02:50:30 +00:00
cephfs: add snap reserve/unreserve and snap exist functionalities
Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
This commit is contained in:
parent
38d005e4e6
commit
5bceb590fd
@ -246,3 +246,132 @@ func reserveVol(ctx context.Context, volOptions *volumeOptions, secret map[strin
|
||||
|
||||
return &vid, nil
|
||||
}
|
||||
|
||||
// reserveSnap is a helper routine to request a UUID reservation for the CSI SnapName and,
|
||||
// to generate the snapshot identifier for the reserved UUID.
|
||||
func reserveSnap(ctx context.Context, volOptions *volumeOptions, parentSubVolName string, snap *cephfsSnapshot, cr *util.Credentials) (*snapshotIdentifier, error) {
|
||||
var (
|
||||
vid snapshotIdentifier
|
||||
imageUUID string
|
||||
err error
|
||||
)
|
||||
|
||||
j, err := snapJournal.Connect(volOptions.Monitors, cr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer j.Destroy()
|
||||
|
||||
imageUUID, vid.FsSnapshotName, err = j.ReserveName(
|
||||
ctx, volOptions.MetadataPool, util.InvalidPoolID,
|
||||
volOptions.MetadataPool, util.InvalidPoolID, snap.RequestName,
|
||||
snap.NamePrefix, parentSubVolName, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// generate the snapshot ID to return to the CO system
|
||||
vid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
|
||||
"", volOptions.ClusterID, imageUUID, volIDVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
util.DebugLog(ctx, "Generated Snapshot ID (%s) for request name (%s)",
|
||||
vid.SnapshotID, snap.RequestName)
|
||||
|
||||
return &vid, nil
|
||||
}
|
||||
|
||||
// undoSnapReservation is a helper routine to undo a name reservation for a CSI SnapshotName.
|
||||
func undoSnapReservation(ctx context.Context, volOptions *volumeOptions, vid snapshotIdentifier, snapName string, cr *util.Credentials) error {
|
||||
j, err := snapJournal.Connect(volOptions.Monitors, cr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer j.Destroy()
|
||||
|
||||
err = j.UndoReservation(ctx, volOptions.MetadataPool,
|
||||
volOptions.MetadataPool, vid.FsSnapshotName, snapName)
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
checkSnapExists checks to determine if passed in RequestName in volOptions exists on the backend.
|
||||
|
||||
**NOTE:** These functions manipulate the rados omaps that hold information regarding
|
||||
volume names as requested by the CSI drivers. Hence, these need to be invoked only when the
|
||||
respective CSI driver generated volume name based locks are held, as otherwise racy
|
||||
access to these omaps may end up leaving them in an inconsistent state.
|
||||
|
||||
These functions also cleanup omap reservations that are stale. I.e when omap entries exist and
|
||||
backing subvolumes are missing, or one of the omaps exist and the next is missing. This is
|
||||
because, the order of omap creation and deletion are inverse of each other, and protected by the
|
||||
request name lock, and hence any stale omaps are leftovers from incomplete transactions and are
|
||||
hence safe to garbage collect.
|
||||
*/
|
||||
func checkSnapExists(
|
||||
ctx context.Context,
|
||||
volOptions *volumeOptions,
|
||||
parentSubVolName string,
|
||||
snap *cephfsSnapshot,
|
||||
cr *util.Credentials) (*snapshotIdentifier, *snapshotInfo, error) {
|
||||
j, err := snapJournal.Connect(volOptions.Monitors, cr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer j.Destroy()
|
||||
|
||||
snapData, err := j.CheckReservation(
|
||||
ctx, volOptions.MetadataPool, snap.RequestName, snap.NamePrefix, parentSubVolName, "")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if snapData == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
sid := &snapshotIdentifier{}
|
||||
snapUUID := snapData.ImageUUID
|
||||
snapID := snapData.ImageAttributes.ImageName
|
||||
sid.FsSnapshotName = snapData.ImageAttributes.ImageName
|
||||
snapInfo, err := getSnapshotInfo(ctx, volOptions, cr, volumeID(snapID), volumeID(parentSubVolName))
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrSnapNotFound) {
|
||||
err = j.UndoReservation(ctx, volOptions.MetadataPool,
|
||||
volOptions.MetadataPool, snapID, snap.RequestName)
|
||||
return nil, nil, err
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err = deleteSnapshot(ctx, volOptions, cr, volumeID(snapID), volumeID(parentSubVolName))
|
||||
if err != nil {
|
||||
klog.Errorf(util.Log(ctx, "failed to delete snapshot %s: %v"), snapID, err)
|
||||
return
|
||||
}
|
||||
err = j.UndoReservation(ctx, volOptions.MetadataPool,
|
||||
volOptions.MetadataPool, snapID, snap.RequestName)
|
||||
if err != nil {
|
||||
klog.Errorf(util.Log(ctx, "removing reservation failed for snapshot %s: %v"), snapID, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
tm, err := parseTime(ctx, snapInfo.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sid.CreationTime = tm
|
||||
// found a snapshot already available, process and return it!
|
||||
sid.SnapshotID, err = util.GenerateVolID(ctx, volOptions.Monitors, cr, volOptions.FscID,
|
||||
"", volOptions.ClusterID, snapUUID, volIDVersion)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
util.DebugLog(ctx, "Found existing snapshot (%s) with subvolume name (%s) for request (%s)",
|
||||
snapData.ImageAttributes.RequestName, parentSubVolName, sid.FsSnapshotName)
|
||||
|
||||
return sid, &snapInfo, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user