diff --git a/internal/rbd/controllerserver.go b/internal/rbd/controllerserver.go index 3ec067c3e..eb37a8063 100644 --- a/internal/rbd/controllerserver.go +++ b/internal/rbd/controllerserver.go @@ -1471,27 +1471,9 @@ func (cs *ControllerServer) DeleteSnapshot( // Deleting snapshot and cloned volume log.DebugLog(ctx, "deleting cloned rbd volume %s", rbdSnap.RbdSnapName) - rbdVol := rbdSnap.toVolume() - - err = rbdVol.Connect(cr) + err = rbdSnap.Delete(ctx) if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - defer rbdVol.Destroy(ctx) - - rbdVol.ImageID = rbdSnap.ImageID - // update parent name to delete the snapshot - rbdSnap.RbdImageName = rbdVol.RbdImageName - err = cleanUpSnapshot(ctx, rbdVol, rbdSnap, rbdVol) - if err != nil { - log.ErrorLog(ctx, "failed to delete image: %v", err) - - return nil, status.Error(codes.Internal, err.Error()) - } - err = undoSnapReservation(ctx, rbdSnap, cr) - if err != nil { - log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) on image (%s) (%s)", - rbdSnap.RequestName, rbdSnap.RbdSnapName, rbdSnap.RbdImageName, err) + log.ErrorLog(ctx, "failed to delete rbd snapshot: %s with error: %v", rbdSnap, err) return nil, status.Error(codes.Internal, err.Error()) } diff --git a/internal/rbd/rbd_util.go b/internal/rbd/rbd_util.go index fbae7f418..343d63708 100644 --- a/internal/rbd/rbd_util.go +++ b/internal/rbd/rbd_util.go @@ -680,6 +680,10 @@ func (ri *rbdImage) Delete(ctx context.Context) error { rbdImage := librbd.GetImage(ri.ioctx, image) err = rbdImage.Trash(0) if err != nil { + if errors.Is(err, librbd.ErrNotFound) { + return fmt.Errorf("Failed as %w (internal %w)", ErrImageNotFound, err) + } + log.ErrorLog(ctx, "failed to delete rbd image: %s, error: %v", ri, err) return err diff --git a/internal/rbd/snapshot.go b/internal/rbd/snapshot.go index 6a06cefc2..ba6f640ab 100644 --- a/internal/rbd/snapshot.go +++ b/internal/rbd/snapshot.go @@ -82,7 +82,7 @@ func cleanUpSnapshot( ) error { err := parentVol.deleteSnapshot(ctx, rbdSnap) if err != nil { - if !errors.Is(err, ErrSnapNotFound) { + if !errors.Is(err, ErrImageNotFound) && !errors.Is(err, ErrSnapNotFound) { log.ErrorLog(ctx, "failed to delete snapshot %q: %v", rbdSnap, err) return err @@ -162,6 +162,42 @@ func (rbdSnap *rbdSnapshot) ToCSI(ctx context.Context) (*csi.Snapshot, error) { }, nil } +// Delete removes the snapshot from the RBD image and then +// the RBD image itself. If the backing RBD snapshot and image is removed +// successfully, the reservation for the snapshot is removed from the journal. +// +// NOTE: As the function manipulates omaps, it should be called with a lock against the request name +// held, to prevent parallel operations from modifying the state of the omaps for this request name. +func (rbdSnap *rbdSnapshot) Delete(ctx context.Context) error { + rbdVol := rbdSnap.toVolume() + + err := rbdVol.Connect(rbdSnap.conn.Creds) + if err != nil { + return err + } + defer rbdVol.Destroy(ctx) + + rbdVol.ImageID = rbdSnap.ImageID + // update parent name to delete the snapshot + rbdSnap.RbdImageName = rbdVol.RbdImageName + err = cleanUpSnapshot(ctx, rbdVol, rbdSnap, rbdVol) + if err != nil { + log.ErrorLog(ctx, "failed to cleanup image %s and snapshot %s: %v", rbdVol, rbdSnap, err) + + return err + } + + err = undoSnapReservation(ctx, rbdSnap, rbdSnap.conn.Creds) + if err != nil { + log.ErrorLog(ctx, "failed to remove reservation for snapname (%s) with backing snap (%s) on image (%s) (%s)", + rbdSnap.RequestName, rbdSnap.RbdSnapName, rbdSnap.RbdImageName, err) + + return err + } + + return nil +} + func undoSnapshotCloning( ctx context.Context, parentVol *rbdVolume,