diff --git a/e2e/rbd.go b/e2e/rbd.go index c0756c7fe..26abed41c 100644 --- a/e2e/rbd.go +++ b/e2e/rbd.go @@ -1250,6 +1250,15 @@ var _ = Describe("RBD", func() { if err != nil { e2elog.Failf("failed to delete snapshotclass with error %v", err) } + // validate images in trash + err = waitToRemoveImagesFromTrash(f, clonePool, deployTimeout) + if err != nil { + e2elog.Failf("failed to validate rbd images in pool %s trash with error %v", clonePool, err) + } + err = waitToRemoveImagesFromTrash(f, defaultRBDPool, deployTimeout) + if err != nil { + e2elog.Failf("failed to validate rbd images in pool %s trash with error %v", defaultRBDPool, err) + } err = deletePool(clonePool, false, f) if err != nil { @@ -1812,6 +1821,14 @@ var _ = Describe("RBD", func() { } }) + + By("validate stale images in trash", func() { + err := waitToRemoveImagesFromTrash(f, defaultRBDPool, deployTimeout) + if err != nil { + e2elog.Failf("failed to validate rbd images in pool %s trash with error %v", defaultRBDPool, err) + } + }) + // Make sure this should be last testcase in this file, because // it deletes pool By("Create a PVC and delete PVC when backend pool deleted", func() { diff --git a/e2e/rbd_helper.go b/e2e/rbd_helper.go index 500acb302..c917a77cd 100644 --- a/e2e/rbd_helper.go +++ b/e2e/rbd_helper.go @@ -3,16 +3,19 @@ package e2e import ( "context" "encoding/json" + "errors" "fmt" "regexp" "strings" "sync" + "time" "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1" v1 "k8s.io/api/core/v1" scv1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/test/e2e/framework" e2elog "k8s.io/kubernetes/test/e2e/framework/log" @@ -762,3 +765,50 @@ func validateThickPVC(f *framework.Framework, pvc *v1.PersistentVolumeClaim, siz return nil } + +// trashInfo contains the image details in trash. +type trashInfo struct { + Name string `json:"name"` +} + +// listRBDImagesInTrash lists images in the trash. +func listRBDImagesInTrash(f *framework.Framework, poolName string) ([]trashInfo, error) { + var trashInfos []trashInfo + + stdout, stdErr, err := execCommandInToolBoxPod(f, + fmt.Sprintf("rbd trash ls --format=json %s", poolName), rookNamespace) + if err != nil { + return trashInfos, err + } + if stdErr != "" { + return trashInfos, fmt.Errorf("failed to list images in trash %v", stdErr) + } + + err = json.Unmarshal([]byte(stdout), &trashInfos) + if err != nil { + return trashInfos, err + } + return trashInfos, nil +} + +func waitToRemoveImagesFromTrash(f *framework.Framework, poolName string, t int) error { + var errReason error + timeout := time.Duration(t) * time.Minute + err := wait.PollImmediate(poll, timeout, func() (bool, error) { + imagesInTrash, err := listRBDImagesInTrash(f, poolName) + if err != nil { + return false, err + } + if len(imagesInTrash) == 0 { + return true, nil + } + errReason = fmt.Errorf("found %d images found in trash. Image details %v", len(imagesInTrash), imagesInTrash) + e2elog.Logf(errReason.Error()) + return false, nil + }) + + if errors.Is(err, wait.ErrWaitTimeout) { + err = errReason + } + return err +}