Skip to content

Commit 97a48d0

Browse files
iPraveenPariharmergify[bot]
authored andcommitted
e2e: validate image features on temp clone and snapshot backing images
Add an e2e test that verifies the intermediate RBD images created during snapshot and clone operations inherit StorageClass image features. Specifically validates: - csi-snap-* (snapshot backing image) inherits features from parent - csi-vol-*-temp (temp clone image) inherits features from parent Signed-off-by: Praveen M <m.praveen@ibm.com> (cherry picked from commit 0e81334) # Conflicts: # e2e/rbd.go # e2e/rbd_helper.go
1 parent f7aebb5 commit 97a48d0

2 files changed

Lines changed: 292 additions & 0 deletions

File tree

e2e/rbd.go

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,9 +2094,258 @@ var _ = Describe("RBD", func() {
20942094
}
20952095
})
20962096

2097+
<<<<<<< HEAD
20972098
ByFileAndBlockEncryption("create a PVC and bind it to an app using rbd-nbd mounter with encryption", func(
20982099
validator encryptionValidateFunc, _ validateFunc, encType crypto.EncryptionType,
20992100
) {
2101+
=======
2102+
It("create PVC with layering,deep-flatten image-features and bind it to an app",
2103+
func() {
2104+
err := deleteResource(rbdExamplePath + "storageclass.yaml")
2105+
if err != nil {
2106+
logAndFail("failed to delete storageclass: %v", err)
2107+
}
2108+
err = createRBDStorageClass(
2109+
f.ClientSet,
2110+
f,
2111+
defaultSCName,
2112+
nil,
2113+
map[string]string{
2114+
"imageFeatures": "layering,deep-flatten",
2115+
},
2116+
deletePolicy)
2117+
if err != nil {
2118+
logAndFail("failed to create storageclass: %v", err)
2119+
}
2120+
// set up PVC
2121+
pvc, err := loadPVC(pvcPath)
2122+
if err != nil {
2123+
logAndFail("failed to load PVC: %v", err)
2124+
}
2125+
pvc.Namespace = f.UniqueName
2126+
err = createPVCAndvalidatePV(f.ClientSet, pvc, deployTimeout)
2127+
if err != nil {
2128+
logAndFail("failed to create PVC: %v", err)
2129+
}
2130+
// validate created backend rbd images
2131+
validateRBDImageCount(f, 1, defaultRBDPool)
2132+
validateOmapCount(f, 1, rbdType, defaultRBDPool, volumesType)
2133+
2134+
if kernel.CheckKernelSupport(kernelRelease, deepFlattenSupport) {
2135+
app, aErr := loadApp(appPath)
2136+
if aErr != nil {
2137+
logAndFail("failed to load application: %v", aErr)
2138+
}
2139+
app.Namespace = f.UniqueName
2140+
err = createApp(f.ClientSet, app, deployTimeout)
2141+
if err != nil {
2142+
logAndFail("failed to create application: %v", err)
2143+
}
2144+
// delete pod as we should not create snapshot for in-use pvc
2145+
err = deletePod(app.Name, app.Namespace, f.ClientSet, deployTimeout)
2146+
if err != nil {
2147+
logAndFail("failed to delete application: %v", err)
2148+
}
2149+
2150+
}
2151+
// clean up after ourselves
2152+
err = deletePVCAndValidatePV(f.ClientSet, pvc, deployTimeout)
2153+
if err != nil {
2154+
logAndFail("failed to delete PVC: %v", err)
2155+
}
2156+
// validate created backend rbd images
2157+
validateRBDImageCount(f, 0, defaultRBDPool)
2158+
validateOmapCount(f, 0, rbdType, defaultRBDPool, volumesType)
2159+
})
2160+
2161+
It("verify temp clone and snapshot backing images inherit StorageClass image features",
2162+
func() {
2163+
if !kernel.CheckKernelSupport(kernelRelease, fastDiffSupport) {
2164+
Skip("kernel does not support fast-diff, skipping image features inheritance test")
2165+
}
2166+
2167+
imageFeatures := "layering,exclusive-lock,object-map,fast-diff,deep-flatten"
2168+
expectedFeatures := []string{
2169+
"layering", "exclusive-lock", "object-map", "fast-diff", "deep-flatten",
2170+
}
2171+
2172+
err := deleteResource(rbdExamplePath + "storageclass.yaml")
2173+
if err != nil {
2174+
logAndFail("failed to delete storageclass: %v", err)
2175+
}
2176+
err = createRBDStorageClass(
2177+
f.ClientSet,
2178+
f,
2179+
defaultSCName,
2180+
nil,
2181+
map[string]string{
2182+
"imageFeatures": imageFeatures,
2183+
},
2184+
deletePolicy)
2185+
if err != nil {
2186+
logAndFail("failed to create storageclass: %v", err)
2187+
}
2188+
defer func() {
2189+
err = deleteResource(rbdExamplePath + "storageclass.yaml")
2190+
if err != nil {
2191+
logAndFail("failed to delete storageclass: %v", err)
2192+
}
2193+
err = createRBDStorageClass(f.ClientSet, f, defaultSCName, nil, nil, deletePolicy)
2194+
if err != nil {
2195+
logAndFail("failed to create storageclass: %v", err)
2196+
}
2197+
}()
2198+
2199+
// create source PVC
2200+
pvc, err := loadPVC(pvcPath)
2201+
if err != nil {
2202+
logAndFail("failed to load PVC: %v", err)
2203+
}
2204+
pvc.Namespace = f.UniqueName
2205+
err = createPVCAndvalidatePV(f.ClientSet, pvc, deployTimeout)
2206+
if err != nil {
2207+
logAndFail("failed to create PVC: %v", err)
2208+
}
2209+
2210+
// create a snapshot and verify the backing image (csi-snap-*)
2211+
// inherits StorageClass image features
2212+
err = createRBDSnapshotClass(f)
2213+
if err != nil {
2214+
logAndFail("failed to create snapshotclass: %v", err)
2215+
}
2216+
defer func() {
2217+
err = deleteRBDSnapshotClass()
2218+
if err != nil {
2219+
logAndFail("failed to delete snapshotclass: %v", err)
2220+
}
2221+
}()
2222+
2223+
snap := getSnapshot(snapshotPath)
2224+
snap.Namespace = f.UniqueName
2225+
snap.Spec.Source.PersistentVolumeClaimName = &pvc.Name
2226+
err = createSnapshot(&snap, deployTimeout)
2227+
if err != nil {
2228+
logAndFail("failed to create snapshot: %v", err)
2229+
}
2230+
2231+
snapImageName, err := getSnapName(snap.Namespace, snap.Name)
2232+
if err != nil {
2233+
logAndFail("failed to get snapshot image name: %v", err)
2234+
}
2235+
err = validateImageFeatures(f, snapImageName, defaultRBDPool, expectedFeatures)
2236+
if err != nil {
2237+
logAndFail("snapshot backing image %s features validation failed: %v",
2238+
snapImageName, err)
2239+
}
2240+
2241+
err = deleteSnapshot(&snap, deployTimeout)
2242+
if err != nil {
2243+
logAndFail("failed to delete snapshot: %v", err)
2244+
}
2245+
2246+
// create a PVC-PVC clone and verify the temp clone image
2247+
// (csi-vol-*-temp) inherits StorageClass image features
2248+
pvcSmartClone, err := loadPVC(pvcSmartClonePath)
2249+
if err != nil {
2250+
logAndFail("failed to load PVC: %v", err)
2251+
}
2252+
pvcSmartClone.Namespace = f.UniqueName
2253+
pvcSmartClone.Spec.DataSource.Name = pvc.Name
2254+
err = createPVCAndvalidatePV(f.ClientSet, pvcSmartClone, deployTimeout)
2255+
if err != nil {
2256+
logAndFail("failed to create cloned PVC: %v", err)
2257+
}
2258+
2259+
// the temp clone image name is the clone image name + "-temp"
2260+
imageData, err := getImageInfoFromPVC(pvcSmartClone.Namespace, pvcSmartClone.Name, f)
2261+
if err != nil {
2262+
logAndFail("failed to get image info from source PVC: %v", err)
2263+
}
2264+
tempCloneImageName := imageData.imageName + "-temp"
2265+
err = validateImageFeatures(f, tempCloneImageName, defaultRBDPool, expectedFeatures)
2266+
if err != nil {
2267+
logAndFail("temp clone image %s features validation failed: %v",
2268+
tempCloneImageName, err)
2269+
}
2270+
2271+
// clean up clone and source
2272+
err = deletePVCAndValidatePV(f.ClientSet, pvcSmartClone, deployTimeout)
2273+
if err != nil {
2274+
logAndFail("failed to delete cloned PVC: %v", err)
2275+
}
2276+
err = deletePVCAndValidatePV(f.ClientSet, pvc, deployTimeout)
2277+
if err != nil {
2278+
logAndFail("failed to delete source PVC: %v", err)
2279+
}
2280+
2281+
validateRBDImageCount(f, 0, defaultRBDPool)
2282+
validateOmapCount(f, 0, rbdType, defaultRBDPool, volumesType)
2283+
})
2284+
2285+
It("create PVC without layering,deep-flatten image-features and bind it to an app",
2286+
func() {
2287+
err := deleteResource(rbdExamplePath + "storageclass.yaml")
2288+
if err != nil {
2289+
logAndFail("failed to delete storageclass: %v", err)
2290+
}
2291+
err = createRBDStorageClass(
2292+
f.ClientSet,
2293+
f,
2294+
defaultSCName,
2295+
nil,
2296+
map[string]string{
2297+
"imageFeatures": "",
2298+
},
2299+
deletePolicy)
2300+
if err != nil {
2301+
logAndFail("failed to create storageclass: %v", err)
2302+
}
2303+
// set up PVC
2304+
pvc, err := loadPVC(pvcPath)
2305+
if err != nil {
2306+
logAndFail("failed to load PVC: %v", err)
2307+
}
2308+
pvc.Namespace = f.UniqueName
2309+
err = createPVCAndvalidatePV(f.ClientSet, pvc, deployTimeout)
2310+
if err != nil {
2311+
logAndFail("failed to create PVC: %v", err)
2312+
}
2313+
// validate created backend rbd images
2314+
validateRBDImageCount(f, 1, defaultRBDPool)
2315+
validateOmapCount(f, 1, rbdType, defaultRBDPool, volumesType)
2316+
2317+
// checking the minimal kernel version for fast-diff as its
2318+
// higher kernel version than other default image features.
2319+
if kernel.CheckKernelSupport(kernelRelease, fastDiffSupport) {
2320+
app, aErr := loadApp(appPath)
2321+
if aErr != nil {
2322+
logAndFail("failed to load application: %v", aErr)
2323+
}
2324+
app.Namespace = f.UniqueName
2325+
err = createApp(f.ClientSet, app, deployTimeout)
2326+
if err != nil {
2327+
logAndFail("failed to create application: %v", err)
2328+
}
2329+
// delete pod as we should not create snapshot for in-use pvc
2330+
err = deletePod(app.Name, app.Namespace, f.ClientSet, deployTimeout)
2331+
if err != nil {
2332+
logAndFail("failed to delete application: %v", err)
2333+
}
2334+
2335+
}
2336+
// clean up after ourselves
2337+
err = deletePVCAndValidatePV(f.ClientSet, pvc, deployTimeout)
2338+
if err != nil {
2339+
logAndFail("failed to delete PVC: %v", err)
2340+
}
2341+
// validate created backend rbd images
2342+
validateRBDImageCount(f, 0, defaultRBDPool)
2343+
validateOmapCount(f, 0, rbdType, defaultRBDPool, volumesType)
2344+
})
2345+
2346+
It("create PVC with journaling,fast-diff image-features and bind it to an app using rbd-nbd mounter",
2347+
func() {
2348+
>>>>>>> 0e81334a (e2e: validate image features on temp clone and snapshot backing images)
21002349
if !testNBD {
21012350
framework.Logf("skipping NBD test")
21022351

e2e/rbd_helper.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,10 +1223,19 @@ func waitToRemoveImagesFromTrash(f *framework.Framework, poolName string, t int)
12231223

12241224
// imageInfo strongly typed JSON spec for image info.
12251225
type imageInfo struct {
1226+
<<<<<<< HEAD
12261227
Name string `json:"name"`
12271228
StripeUnit int `json:"stripe_unit"`
12281229
StripeCount int `json:"stripe_count"`
12291230
ObjectSize int `json:"object_size"`
1231+
=======
1232+
Name string `json:"name"`
1233+
StripeUnit int `json:"stripe_unit"`
1234+
StripeCount int `json:"stripe_count"`
1235+
ObjectSize int `json:"object_size"`
1236+
DataPool string `json:"data_pool"`
1237+
Features []string `json:"features"`
1238+
>>>>>>> 0e81334a (e2e: validate image features on temp clone and snapshot backing images)
12301239
}
12311240

12321241
// getImageInfo queries rbd about the given image and returns its metadata, and returns
@@ -1305,6 +1314,40 @@ func validateStripe(f *framework.Framework,
13051314
return nil
13061315
}
13071316

1317+
// validateImageFeatures checks that the given RBD image has all the expected
1318+
// image features enabled.
1319+
func validateImageFeatures(
1320+
f *framework.Framework,
1321+
imageName, pool string,
1322+
expectedFeatures []string,
1323+
) error {
1324+
var imgInfo imageInfo
1325+
1326+
imgInfoStr, err := getImageInfo(f, imageName, pool)
1327+
if err != nil {
1328+
return err
1329+
}
1330+
1331+
err = json.Unmarshal([]byte(imgInfoStr), &imgInfo)
1332+
if err != nil {
1333+
return fmt.Errorf("unmarshal failed: %w. raw buffer response: %s", err, imgInfoStr)
1334+
}
1335+
1336+
actualSet := make(map[string]bool, len(imgInfo.Features))
1337+
for _, feat := range imgInfo.Features {
1338+
actualSet[feat] = true
1339+
}
1340+
1341+
for _, want := range expectedFeatures {
1342+
if !actualSet[want] {
1343+
return fmt.Errorf("image %s missing expected feature %q, got features: %v",
1344+
imageName, want, imgInfo.Features)
1345+
}
1346+
}
1347+
1348+
return nil
1349+
}
1350+
13081351
func validateQOS(f *framework.Framework,
13091352
pvc *v1.PersistentVolumeClaim,
13101353
wants map[string]string,

0 commit comments

Comments
 (0)