Skip to content

Commit ff69aae

Browse files
committed
Enhance storageclass validation for linkedclone volume creation
Signed-off-by: Deepak Kinni <[email protected]>
1 parent b28f50c commit ff69aae

File tree

2 files changed

+608
-7
lines changed

2 files changed

+608
-7
lines changed

pkg/syncer/admissionhandler/validatepvc.go

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,8 @@ func validateGuestPVCOperation(ctx context.Context, req *admissionv1.AdmissionRe
319319

320320
// ValidateLinkedCloneRequest validates the various conditions necessary for a valid linkedclone request.
321321
// 1. The PVC datasource needs to be of type VolumeSnapshot
322-
// 2. The storageclass associated LinkedClone PVC should be the same the source PVC
322+
// 2. The svStorageClass parameter in the storageclass associated with the LinkedClone PVC
323+
// should match the svStorageClass in the storageclass of the source PVC
323324
// 3. The size should be the same as the source PVC
324325
// 4. Should not be a second level LinkedClone
325326
// 5. VS is not under deletion
@@ -463,13 +464,89 @@ func validateGuestPVCOperation(ctx context.Context, req *admissionv1.AdmissionRe
463464
}
464465
}
465466

466-
// The storageclass associated LinkedClone PVC should be the same the source PVC
467+
// The svStorageClass parameter in the storageclass associated with the LinkedClone PVC
468+
// should be the same as the svStorageClass in the storageclass of the source PVC
467469
sourcePVCStorageClassName := sourcePVC.Spec.StorageClassName
468-
same := strings.Compare(*pvc.Spec.StorageClassName, *sourcePVCStorageClassName)
469-
if same != 0 {
470-
errMsg := fmt.Sprintf("StorageClass mismatch, Namespace: %s, LinkedClone StorageClass: "+
471-
"%s, source PVC StorageClass: %s", sourcePVC.Namespace, *pvc.Spec.StorageClassName,
472-
*sourcePVCStorageClassName)
470+
linkedClonePVCStorageClassName := pvc.Spec.StorageClassName
471+
472+
// Retrieve the StorageClass objects
473+
sourceStorageClass, err := k8sClient.StorageV1().StorageClasses().Get(ctx, *sourcePVCStorageClassName,
474+
metav1.GetOptions{})
475+
if err != nil {
476+
errMsg := fmt.Sprintf("error getting source PVC StorageClass %s from api server: %v",
477+
*sourcePVCStorageClassName, err)
478+
return &admissionv1.AdmissionResponse{
479+
Allowed: false,
480+
Result: &metav1.Status{
481+
Message: errMsg,
482+
},
483+
}
484+
}
485+
486+
linkedCloneStorageClass, err := k8sClient.StorageV1().StorageClasses().Get(ctx, *linkedClonePVCStorageClassName,
487+
metav1.GetOptions{})
488+
if err != nil {
489+
errMsg := fmt.Sprintf("error getting LinkedClone PVC StorageClass %s from api server: %v",
490+
*linkedClonePVCStorageClassName, err)
491+
return &admissionv1.AdmissionResponse{
492+
Allowed: false,
493+
Result: &metav1.Status{
494+
Message: errMsg,
495+
},
496+
}
497+
}
498+
499+
// Extract svStorageClass from StorageClass parameters (case-insensitive lookup)
500+
var sourceSvStorageClass string
501+
var sourceHasSvStorageClass bool
502+
for param, value := range sourceStorageClass.Parameters {
503+
if strings.ToLower(param) == common.AttributeSupervisorStorageClass {
504+
sourceSvStorageClass = value
505+
sourceHasSvStorageClass = true
506+
break
507+
}
508+
}
509+
510+
var linkedCloneSvStorageClass string
511+
var linkedCloneHasSvStorageClass bool
512+
for param, value := range linkedCloneStorageClass.Parameters {
513+
if strings.ToLower(param) == common.AttributeSupervisorStorageClass {
514+
linkedCloneSvStorageClass = value
515+
linkedCloneHasSvStorageClass = true
516+
break
517+
}
518+
}
519+
520+
// Both storage classes must have svStorageClass parameter
521+
if !sourceHasSvStorageClass {
522+
errMsg := fmt.Sprintf("source PVC StorageClass %s does not have %s parameter",
523+
*sourcePVCStorageClassName, common.AttributeSupervisorStorageClass)
524+
return &admissionv1.AdmissionResponse{
525+
Allowed: false,
526+
Result: &metav1.Status{
527+
Message: errMsg,
528+
},
529+
}
530+
}
531+
532+
if !linkedCloneHasSvStorageClass {
533+
errMsg := fmt.Sprintf("LinkedClone PVC StorageClass %s does not have %s parameter",
534+
*linkedClonePVCStorageClassName, common.AttributeSupervisorStorageClass)
535+
return &admissionv1.AdmissionResponse{
536+
Allowed: false,
537+
Result: &metav1.Status{
538+
Message: errMsg,
539+
},
540+
}
541+
}
542+
543+
// Compare svStorageClass values
544+
if strings.Compare(sourceSvStorageClass, linkedCloneSvStorageClass) != 0 {
545+
errMsg := fmt.Sprintf("StorageClass svStorageClass mismatch, Namespace: %s, "+
546+
"LinkedClone StorageClass: %s (svStorageClass: %s), "+
547+
"source PVC StorageClass: %s (svStorageClass: %s)",
548+
sourcePVC.Namespace, *linkedClonePVCStorageClassName, linkedCloneSvStorageClass,
549+
*sourcePVCStorageClassName, sourceSvStorageClass)
473550
return &admissionv1.AdmissionResponse{
474551
Allowed: false,
475552
Result: &metav1.Status{

0 commit comments

Comments
 (0)