diff --git a/e2e/cephfs.go b/e2e/cephfs.go index 6b757ef50..57b91a695 100644 --- a/e2e/cephfs.go +++ b/e2e/cephfs.go @@ -916,6 +916,82 @@ var _ = Describe(cephfsType, func() { } }) + By("Test subvolume snapshot metadata feature", func() { + err := createCephFSSnapshotClass(f) + if err != nil { + e2elog.Failf("failed to create CephFS snapshotclass: %v", err) + } + pvc, err := loadPVC(pvcPath) + if err != nil { + e2elog.Failf("failed to load PVC: %v", err) + } + pvc.Namespace = f.UniqueName + err = createPVCAndvalidatePV(f.ClientSet, pvc, deployTimeout) + if err != nil { + e2elog.Failf("failed to create PVC: %v", err) + } + snap := getSnapshot(snapshotPath) + snap.Namespace = f.UniqueName + snap.Spec.Source.PersistentVolumeClaimName = &pvc.Name + // create snapshot + snap.Name = f.UniqueName + err = createSnapshot(&snap, deployTimeout) + if err != nil { + e2elog.Failf("failed to create snapshot (%s): %v", snap.Name, err) + } + _, pv, err := getPVCAndPV(f.ClientSet, pvc.Name, pvc.Namespace) + if err != nil { + e2elog.Failf("failed to get PV object for %s: %v", pvc.Name, err) + } + subVolumeName := pv.Spec.CSI.VolumeAttributes["subvolumeName"] + snaps, err := listCephFSSnapshots(f, fileSystemName, subVolumeName, subvolumegroup) + if err != nil { + e2elog.Failf("failed to list subvolume snapshots: %v", err) + } + if len(snaps) == 0 { + e2elog.Failf("cephFS snapshots list is empty %s/%s", fileSystemName, subVolumeName) + } + + content, err := getVolumeSnapshotContent(snap.Namespace, snap.Name) + if err != nil { + e2elog.Failf("failed to get snapshotcontent for %s in namespace %s: %v", + snap.Name, snap.Namespace, err) + } + + metadata, err := listCephFSSnapshotMetadata(f, + fileSystemName, subVolumeName, snaps[0].Name, subvolumegroup) + if err != nil { + e2elog.Failf("failed to list subvolume snapshots metadata: %v", err) + } + if metadata.VolSnapNameKey != snap.Name { + e2elog.Failf("failed, snapname expected:%s got:%s", + snap.Name, metadata.VolSnapNameKey) + } else if metadata.VolSnapNamespaceKey != snap.Namespace { + e2elog.Failf("failed, snapnamespace expected:%s got:%s", + snap.Namespace, metadata.VolSnapNamespaceKey) + } else if metadata.VolSnapContentNameKey != content.Name { + e2elog.Failf("failed, contentname expected:%s got:%s", + content.Name, metadata.VolSnapContentNameKey) + } + + // delete snapshot + err = deleteSnapshot(&snap, deployTimeout) + if err != nil { + e2elog.Failf("failed to delete snapshot (%s): %v", f.UniqueName, err) + } + // Delete the parent pvc + err = deletePVCAndValidatePV(f.ClientSet, pvc, deployTimeout) + if err != nil { + e2elog.Failf("failed to delete PVC: %v", err) + } + validateSubvolumeCount(f, 0, fileSystemName, subvolumegroup) + validateOmapCount(f, 0, cephfsType, metadataPool, volumesType) + err = deleteResource(cephFSExamplePath + "snapshotclass.yaml") + if err != nil { + e2elog.Failf("failed to delete CephFS snapshotclass: %v", err) + } + }) + By("Delete snapshot after deleting subvolume and snapshot from backend", func() { err := createCephFSSnapshotClass(f) if err != nil { diff --git a/e2e/cephfs_helper.go b/e2e/cephfs_helper.go index 9f641415f..e096734e5 100644 --- a/e2e/cephfs_helper.go +++ b/e2e/cephfs_helper.go @@ -201,7 +201,7 @@ func listCephFSSubVolumes(f *framework.Framework, filesystem, groupname string) return subVols, err } if stdErr != "" { - return subVols, fmt.Errorf("error listing subolumes %v", stdErr) + return subVols, fmt.Errorf("error listing subvolumes %v", stdErr) } err = json.Unmarshal([]byte(stdout), &subVols) @@ -224,20 +224,20 @@ func listCephFSSubvolumeMetadata( filesystem, subvolume, groupname string, -) (cephfsSubvolumeMetadata, error) { - var metadata cephfsSubvolumeMetadata +) (*cephfsSubvolumeMetadata, error) { stdout, stdErr, err := execCommandInToolBoxPod( f, fmt.Sprintf("ceph fs subvolume metadata ls %s %s --group_name=%s --format=json", filesystem, subvolume, groupname), rookNamespace) if err != nil { - return metadata, err + return nil, err } if stdErr != "" { - return metadata, fmt.Errorf("error listing subvolume metadata %v", stdErr) + return nil, fmt.Errorf("error listing subvolume metadata %v", stdErr) } - err = json.Unmarshal([]byte(stdout), &metadata) + metadata := &cephfsSubvolumeMetadata{} + err = json.Unmarshal([]byte(stdout), metadata) if err != nil { return metadata, err } @@ -245,6 +245,65 @@ func listCephFSSubvolumeMetadata( return metadata, nil } +type cephfsSnapshotMetadata struct { + VolSnapNameKey string `json:"csi.storage.k8s.io/volumesnapshot/name"` + VolSnapNamespaceKey string `json:"csi.storage.k8s.io/volumesnapshot/namespace"` + VolSnapContentNameKey string `json:"csi.storage.k8s.io/volumesnapshotcontent/name"` +} + +func listCephFSSnapshotMetadata( + f *framework.Framework, + filesystem, + subvolume, + snapname, + groupname string, +) (*cephfsSnapshotMetadata, error) { + stdout, stdErr, err := execCommandInToolBoxPod( + f, + fmt.Sprintf("ceph fs subvolume snapshot metadata ls %s %s %s --group_name=%s --format=json", + filesystem, subvolume, snapname, groupname), + rookNamespace) + if err != nil { + return nil, err + } + if stdErr != "" { + return nil, fmt.Errorf("error listing subvolume snapshots metadata %v", stdErr) + } + + metadata := &cephfsSnapshotMetadata{} + err = json.Unmarshal([]byte(stdout), metadata) + if err != nil { + return metadata, err + } + + return metadata, nil +} + +type cephfsSnapshot struct { + Name string `json:"name"` +} + +func listCephFSSnapshots(f *framework.Framework, filesystem, subvolume, groupname string) ([]cephfsSnapshot, error) { + var snaps []cephfsSnapshot + stdout, stdErr, err := execCommandInToolBoxPod( + f, + fmt.Sprintf("ceph fs subvolume snapshot ls %s %s --group_name=%s --format=json", filesystem, subvolume, groupname), + rookNamespace) + if err != nil { + return snaps, err + } + if stdErr != "" { + return snaps, fmt.Errorf("error listing subolume snapshots %v", stdErr) + } + + err = json.Unmarshal([]byte(stdout), &snaps) + if err != nil { + return snaps, err + } + + return snaps, nil +} + // getSubvolumepath validates whether subvolumegroup is present. func getSubvolumePath(f *framework.Framework, filesystem, subvolgrp, subvolume string) (string, error) { cmd := fmt.Sprintf("ceph fs subvolume getpath %s %s --group_name=%s", filesystem, subvolume, subvolgrp)