@@ -400,6 +400,119 @@ func TestPod_Single_SSD_Luks_Volume_Snapshot(t *testing.T) {
400400 waitCloudscaleVolumeDeleted (t , pvc .Spec .VolumeName )
401401}
402402
403+ func TestPod_Create_Raw_Block_Volume_From_Snapshot (t * testing.T ) {
404+ podDescriptor := TestPodDescriptor {
405+ Kind : "Pod" ,
406+ Name : pseudoUuid (),
407+ Volumes : []TestPodVolume {
408+ {
409+ ClaimName : "csi-pod-ssd-raw-pvc-original" ,
410+ SizeGB : 5 ,
411+ StorageClass : "cloudscale-volume-ssd" ,
412+ Block : true ,
413+ },
414+ },
415+ }
416+
417+ // submit the pod and the pvc
418+ pod := makeKubernetesPod (t , podDescriptor )
419+ pvcs := makeKubernetesPVCs (t , podDescriptor )
420+ assert .Equal (t , 1 , len (pvcs ))
421+
422+ // wait for the pod to be running and verify that the pvc is bound
423+ waitForPod (t , client , pod .Name )
424+ pvc := getPVC (t , client , pvcs [0 ].Name )
425+ assert .Equal (t , v1 .ClaimBound , pvc .Status .Phase )
426+
427+ // load the volume from the cloudscale.ch api and verify that it
428+ // has the requested size and volume type
429+ originalVolume := getCloudscaleVolume (t , pvc .Spec .VolumeName )
430+ assert .Equal (t , 5 , originalVolume .SizeGB )
431+ assert .Equal (t , "ssd" , originalVolume .Type )
432+
433+ // verify the disk is a raw block device with no filesystem
434+ disk , err := getVolumeInfo (t , pod , pvc .Spec .VolumeName )
435+ assert .NoError (t , err )
436+ assert .Equal (t , "" , disk .Luks )
437+ assert .Equal (t , "Block" , disk .PVCVolumeMode )
438+ assert .Equal (t , "" , disk .Filesystem )
439+ assert .Equal (t , 5 * driver .GB , disk .DeviceSize )
440+ assert .Equal (t , - 1 , disk .FilesystemSize )
441+
442+ // create a snapshot of the raw block volume
443+ snapshotName := pseudoUuid ()
444+ snapshot := makeKubernetesVolumeSnapshot (t , snapshotName , pvc .Name )
445+
446+ // wait for the snapshot to be ready
447+ waitForVolumeSnapshot (t , snapshot .Name )
448+ snapshot = getVolumeSnapshot (t , snapshot .Name )
449+ assert .NotNil (t , snapshot .Status )
450+ assert .NotNil (t , snapshot .Status .BoundVolumeSnapshotContentName )
451+ assert .True (t , * snapshot .Status .ReadyToUse )
452+
453+ // verify the snapshot exists in the cloudscale.ch API
454+ snapshotContent := getVolumeSnapshotContent (t , * snapshot .Status .BoundVolumeSnapshotContentName )
455+ assert .NotNil (t , snapshotContent .Status )
456+ assert .NotNil (t , snapshotContent .Status .SnapshotHandle )
457+
458+ cloudscaleSnapshot := getCloudscaleVolumeSnapshot (t , * snapshotContent .Status .SnapshotHandle )
459+ assert .NotNil (t , cloudscaleSnapshot )
460+ assert .Equal (t , * snapshotContent .Status .SnapshotHandle , cloudscaleSnapshot .UUID )
461+ assert .Equal (t , "available" , cloudscaleSnapshot .Status )
462+ assert .Equal (t , 5 , cloudscaleSnapshot .SizeGB )
463+
464+ // create a new pod with a raw block pvc restored from the snapshot
465+ // we double the increase the size to 10 gb
466+ restoredPodDescriptor := TestPodDescriptor {
467+ Kind : "Pod" ,
468+ Name : pseudoUuid (),
469+ Volumes : []TestPodVolume {
470+ {
471+ ClaimName : "csi-pod-ssd-raw-pvc-restored" ,
472+ SizeGB : 10 ,
473+ StorageClass : "cloudscale-volume-ssd" ,
474+ Block : true ,
475+ },
476+ },
477+ }
478+
479+ restoredPod := makeKubernetesPod (t , restoredPodDescriptor )
480+ restoredPVCs := makeKubernetesPVCsFromSnapshot (t , restoredPodDescriptor , snapshot .Name )
481+ assert .Equal (t , 1 , len (restoredPVCs ))
482+
483+ // wait for the restored pod to be running and verify that the pvc is bound
484+ waitForPod (t , client , restoredPod .Name )
485+ restoredPVC := getPVC (t , client , restoredPVCs [0 ].Name )
486+ assert .Equal (t , v1 .ClaimBound , restoredPVC .Status .Phase )
487+
488+ // load the restored volume from the cloudscale.ch api and verify that it
489+ // has the requested size and volume type
490+ restoredVolume := getCloudscaleVolume (t , restoredPVC .Spec .VolumeName )
491+ assert .Equal (t , 10 , restoredVolume .SizeGB )
492+ assert .Equal (t , "ssd" , restoredVolume .Type )
493+
494+ // verify the restored disk is also a raw block device with no filesystem
495+ restoredDisk , err := getVolumeInfo (t , restoredPod , restoredPVC .Spec .VolumeName )
496+ assert .NoError (t , err )
497+ assert .Equal (t , "" , restoredDisk .Luks )
498+ assert .Equal (t , "Block" , restoredDisk .PVCVolumeMode )
499+ assert .Equal (t , "" , restoredDisk .Filesystem )
500+ assert .Equal (t , 10 * driver .GB , restoredDisk .DeviceSize )
501+ assert .Equal (t , - 1 , restoredDisk .FilesystemSize )
502+
503+ // delete the snapshot before deleting the volumes (cloudscale requires snapshots deleted before source volume)
504+ deleteKubernetesVolumeSnapshot (t , snapshot .Name )
505+ waitCloudscaleVolumeSnapshotDeleted (t , * snapshotContent .Status .SnapshotHandle )
506+
507+ // cleanup restored pod and pvc
508+ cleanup (t , restoredPodDescriptor )
509+ waitCloudscaleVolumeDeleted (t , restoredPVC .Spec .VolumeName )
510+
511+ // cleanup original pod and pvc
512+ cleanup (t , podDescriptor )
513+ waitCloudscaleVolumeDeleted (t , pvc .Spec .VolumeName )
514+ }
515+
403516func TestPod_Snapshot_Restore_Larger_Size (t * testing.T ) {
404517 podDescriptor := TestPodDescriptor {
405518 Kind : "Pod" ,
0 commit comments