@@ -2456,47 +2456,146 @@ func (vs *vSphereVMProvider) vmCreateGenConfigSpecImagePVCDataSourceRefs(
24562456 vmCtx pkgctx.VirtualMachineContext ,
24572457 createArgs * VMCreateArgs ) error {
24582458
2459- _ , _ = vmCtx , createArgs // Remove once args are used.
2459+ if createArgs .ConfigSpec .DeviceChange == nil {
2460+ return nil
2461+ }
24602462
2461- // TODO(AllDisksArePVCs)
2462- //
2463- // Implement this function. For example, for each of the disks in
2464- // createArgs.ConfigSpec, do the following:
2465- //
2466- // 1. Iterate over spec.volumes and look for an entry with an
2467- // unmanagedVolumeSource with a type of "FromImage" and name set to
2468- // the value that identifies the current disk (the logic for
2469- // deriving this name is located in the UpdateVmiWithOVF and
2470- // UpdateVmiWithVirtualMachine functions in the file
2471- // pkg/providers/vsphere/contentlibrary/content_library_utils.go).
2472- //
2473- // 2. If no such entry exists, then continue to the next iteration of the
2474- // loop.
2475- //
2476- // 3. Use the k8s client's Get function (do not use CreateOrPatch)
2477- // to see if a PersistentVolumeClaim object already exists for
2478- // this disk. The name of the PersistentVolumeClaim object should
2479- // be what was specified in the field
2480- // spec.volumes[].persistentVolumeClaim.claimName from the prior
2481- // step.
2482- //
2483- // If no such entry exists, then return an error indicating the PVC for
2484- // the specified claim is missing and VM creation may not proceed.
2485- //
2486- // 4. Get the PVC's specified storage class and requested capacity.
2487- //
2488- // The PVC *may* specify a different encryption class from the VM, but it
2489- // is probably too much work to handle multiple encryption classes in our
2490- // BYOK reconciler at this point. We will allow the PVC to be recrypted
2491- // by CSI *after* the VM is created and the disk is turned into a PVC.
2492- //
2493- // Update the disk device's specified storage class using the value from
2494- // the PVC. Update the disk device's specified capacity using the value
2495- // from the PVC *if* it is larger than the disk's current requested size.
2496- //
2497- // That should be it! We are not actually registering these disks as PVCs
2498- // at this point. That happens in the VM's update workflow later. For now
2499- // we just need the information about these disks *from* the PVCs.
2463+ // lookup map to avoid iterating over the volumes for each disk
2464+ unmanagedVolumeClaimsFromImage := make (map [string ]vmopv1.VirtualMachineVolume )
2465+ for _ , vol := range vmCtx .VM .Spec .Volumes {
2466+ if vol .PersistentVolumeClaim == nil {
2467+ continue
2468+ }
2469+
2470+ unmanagedVolumeClaim := vol .PersistentVolumeClaim .UnmanagedVolumeClaim
2471+ if unmanagedVolumeClaim == nil {
2472+ continue
2473+ }
2474+
2475+ if unmanagedVolumeClaim .Type != vmopv1 .UnmanagedVolumeClaimVolumeTypeFromImage {
2476+ continue
2477+ }
2478+
2479+ unmanagedVolumeClaimsFromImage [unmanagedVolumeClaim .Name ] = vol
2480+ }
2481+
2482+ var errs []error
2483+
2484+ for _ , deviceChange := range createArgs .ConfigSpec .DeviceChange {
2485+ if deviceSpec := deviceChange .GetVirtualDeviceConfigSpec (); deviceSpec != nil {
2486+ if disk , ok := deviceSpec .Device .(* vimtypes.VirtualDisk ); ok {
2487+ if di := disk .DeviceInfo ; di != nil {
2488+ if d := di .GetDescription (); d != nil {
2489+ volume , ok := unmanagedVolumeClaimsFromImage [d .Label ]
2490+ if ok {
2491+ // update the uuid in the disk backing info
2492+ vmCreateGenConfigSpecSetDiskBackingUUID (volume , disk )
2493+
2494+ // update the storage profile and size based on the PVC
2495+ if err := vs .updateDiskDeviceFromPVC (
2496+ vmCtx ,
2497+ volume .PersistentVolumeClaim .ClaimName ,
2498+ createArgs .Storage .StorageClassToPolicyID ,
2499+ deviceSpec ,
2500+ disk ,
2501+ ); err != nil {
2502+ errs = append (errs , err )
2503+ }
2504+ }
2505+ }
2506+ }
2507+ }
2508+ }
2509+ }
2510+
2511+ if len (errs ) > 0 {
2512+ return apierrorsutil .NewAggregate (errs )
2513+ }
2514+
2515+ return nil
2516+ }
2517+
2518+ func vmCreateGenConfigSpecSetDiskBackingUUID (volume vmopv1.VirtualMachineVolume , disk * vimtypes.VirtualDisk ) {
2519+ // The following backing info types do not have a UUID field
2520+ // - VirtualDiskFlatVer1BackingInfo
2521+ // - VirtualDiskSparseVer1BackingInfo
2522+
2523+ switch tb := disk .Backing .(type ) {
2524+ case * vimtypes.VirtualDiskSeSparseBackingInfo :
2525+ tb .Uuid = volume .PersistentVolumeClaim .UnmanagedVolumeClaim .UUID
2526+ case * vimtypes.VirtualDiskSparseVer2BackingInfo :
2527+ tb .Uuid = volume .PersistentVolumeClaim .UnmanagedVolumeClaim .UUID
2528+ case * vimtypes.VirtualDiskFlatVer2BackingInfo :
2529+ tb .Uuid = volume .PersistentVolumeClaim .UnmanagedVolumeClaim .UUID
2530+ case * vimtypes.VirtualDiskLocalPMemBackingInfo :
2531+ tb .Uuid = volume .PersistentVolumeClaim .UnmanagedVolumeClaim .UUID
2532+ case * vimtypes.VirtualDiskRawDiskMappingVer1BackingInfo :
2533+ tb .Uuid = volume .PersistentVolumeClaim .UnmanagedVolumeClaim .UUID
2534+ case * vimtypes.VirtualDiskRawDiskVer2BackingInfo :
2535+ tb .Uuid = volume .PersistentVolumeClaim .UnmanagedVolumeClaim .UUID
2536+ case * vimtypes.VirtualDiskPartitionedRawDiskVer2BackingInfo :
2537+ tb .Uuid = volume .PersistentVolumeClaim .UnmanagedVolumeClaim .UUID
2538+ }
2539+ }
2540+
2541+ func (vs * vSphereVMProvider ) updateDiskDeviceFromPVC (
2542+ vmCtx pkgctx.VirtualMachineContext ,
2543+ claimName string ,
2544+ storageClassToPolicyID map [string ]string ,
2545+ deviceSpec * vimtypes.VirtualDeviceConfigSpec ,
2546+ disk * vimtypes.VirtualDisk ,
2547+ ) error {
2548+ pvc := & corev1.PersistentVolumeClaim {}
2549+ key := ctrlclient.ObjectKey {
2550+ Namespace : vmCtx .VM .Namespace ,
2551+ Name : claimName ,
2552+ }
2553+
2554+ if err := vs .k8sClient .Get (vmCtx , key , pvc ); err != nil {
2555+ if apierrors .IsNotFound (err ) {
2556+ return fmt .Errorf (
2557+ "pvc %s/%s not found for the specified claim" ,
2558+ key .Namespace , key .Name ,
2559+ )
2560+ }
2561+
2562+ return fmt .Errorf (
2563+ "failed to get pvc %s/%s for the specified claim: %w" ,
2564+ key .Namespace , key .Name , err ,
2565+ )
2566+ }
2567+
2568+ // Update disk device with PVC information
2569+ // - Set the profile based on the PVC's storage class
2570+ // - Adjust disk size if PVC requests more than image disk size
2571+ storageClassName := pvc .Spec .StorageClassName
2572+
2573+ if storageClassName == nil ||
2574+ storageClassToPolicyID == nil ||
2575+ storageClassToPolicyID [* storageClassName ] == "" {
2576+
2577+ return fmt .Errorf (
2578+ "pvc %s/%s has no storage class or no Policy IDmapping for the storage class" ,
2579+ key .Namespace , key .Name ,
2580+ )
2581+ }
2582+
2583+ deviceSpec .Profile = []vimtypes.BaseVirtualMachineProfileSpec {
2584+ & vimtypes.VirtualMachineDefinedProfileSpec {
2585+ ProfileId : storageClassToPolicyID [* storageClassName ],
2586+ },
2587+ }
2588+
2589+ if pvcCapacity , ok := pvc .Spec .Resources .Requests [corev1 .ResourceStorage ]; ok && ! pvcCapacity .IsZero () {
2590+ // TODO: Verify this again
2591+ // Is it possible to set the size for a child disk if the VM is a linked clone?
2592+ pvcSizeBytes := pvcCapacity .Value ()
2593+
2594+ diskSizeBytes := disk .CapacityInBytes
2595+ if pvcSizeBytes > diskSizeBytes {
2596+ disk .CapacityInBytes = pvcSizeBytes
2597+ }
2598+ }
25002599
25012600 return nil
25022601}
0 commit comments