@@ -551,6 +551,9 @@ func (v *VmAdapter) Model() model.Model {
551551
552552// Apply the update to the model.
553553func (v * VmAdapter ) Apply (u types.ObjectUpdate ) {
554+ // ctkPerDisk map - CBT enabled disks, we need this here to update the model.Disks
555+ // which on initial state is ready only after the ctkPerDisk update
556+ ctkPerDisk := map [string ]bool {}
554557 v .Base .Apply (& v .model .Base , u )
555558 for _ , p := range u .ChangeSet {
556559 switch p .Op {
@@ -667,29 +670,44 @@ func (v *VmAdapter) Apply(u types.ObjectUpdate) {
667670 if options , cast := p .Val .(types.ArrayOfOptionValue ); cast {
668671 for _ , val := range options .OptionValue {
669672 opt := val .GetOptionValue ()
670- switch opt . Key {
671- case "numa.nodeAffinity" :
673+
674+ if opt . Key == "numa.nodeAffinity" {
672675 if s , cast := opt .Value .(string ); cast {
673676 v .model .NumaNodeAffinity = strings .Split (s , "," )
674677 }
675- case "ctkEnabled" :
678+ } else if opt . Key == "ctkEnabled" {
676679 if s , cast := opt .Value .(string ); cast {
677680 boolVal , err := strconv .ParseBool (s )
678681 if err != nil {
679682 return
680683 }
681684 v .model .ChangeTrackingEnabled = boolVal
682685 }
683- case "disk.EnableUUID" :
686+ } else if opt . Key == "disk.EnableUUID" {
684687 if s , cast := opt .Value .(string ); cast {
685688 boolVal , err := strconv .ParseBool (s )
686689 if err != nil {
687690 return
688691 }
689692 v .model .DiskEnableUuid = boolVal
690693 }
694+ } else if hasDiskPrefix (opt .Key ) && strings .HasSuffix (opt .Key , ".ctkEnabled" ) {
695+
696+ if s , cast := opt .Value .(string ); cast {
697+ boolVal , err := strconv .ParseBool (s )
698+ if err != nil {
699+ return
700+ }
701+ if boolVal {
702+ ctkPerDisk [strings .Split (opt .Key , "." )[0 ]] = true
703+ }
704+ }
691705 }
706+ }
692707
708+ //In case of ExtraConfig update, on initial state model.Disks is not ready yet
709+ if len (v .model .Disks ) > 0 {
710+ isCBTEnabledForDisks (ctkPerDisk , v .model .Disks )
693711 }
694712 }
695713 case fNestedHVEnabled :
@@ -814,12 +832,42 @@ func (v *VmAdapter) Apply(u types.ObjectUpdate) {
814832 v .model .NICs = nicList
815833 v .updateControllers (& devArray )
816834 v .updateDisks (& devArray )
835+
836+ if len (ctkPerDisk ) > 0 {
837+ isCBTEnabledForDisks (ctkPerDisk , v .model .Disks )
838+ }
817839 }
818840 }
819841 }
820842 }
821843}
822844
845+ func hasDiskPrefix (key string ) bool {
846+ return strings .HasPrefix (key , SCSI ) ||
847+ strings .HasPrefix (key , SATA ) ||
848+ strings .HasPrefix (key , IDE ) ||
849+ strings .HasPrefix (key , NVME )
850+ }
851+
852+ func isCBTEnabledForDisks (ctkPerDisk map [string ]bool , disks []model.Disk ) {
853+ for i := range disks {
854+ disk := & disks [i ]
855+
856+ // In vSphere, ControllerKey values are typically large integers that encode the controller bus number.
857+ // To extract the actual controller index (e.g., scsi0, scsi1), we round down to the nearest 100 to get the base,
858+ // then subtract it from the ControllerKey. For example, 16001 → controllerIndex 1 (16001 - 16000).
859+ baseKey := (disk .ControllerKey / 100 ) * 100
860+ controllerIndex := disk .ControllerKey - baseKey
861+ deviceKey := fmt .Sprintf ("%s%d:%d" , disk .Bus , controllerIndex , disk .UnitNumber )
862+
863+ if ctkPerDisk [deviceKey ] {
864+ disk .ChangeTrackingEnabled = true
865+ } else {
866+ disk .ChangeTrackingEnabled = false
867+ }
868+ }
869+ }
870+
823871// Update virtual disk devices.
824872func (v * VmAdapter ) updateControllers (devArray * types.ArrayOfVirtualDevice ) {
825873 controllers := []model.Controller {}
@@ -900,11 +948,13 @@ func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
900948 switch backing := disk .Backing .(type ) {
901949 case * types.VirtualDiskFlatVer1BackingInfo :
902950 md := model.Disk {
903- Key : disk .Key ,
904- File : backing .FileName ,
905- Capacity : disk .CapacityInBytes ,
906- Mode : backing .DiskMode ,
907- Bus : controller .Bus ,
951+ Key : disk .Key ,
952+ UnitNumber : * disk .UnitNumber ,
953+ ControllerKey : disk .ControllerKey ,
954+ File : backing .FileName ,
955+ Capacity : disk .CapacityInBytes ,
956+ Mode : backing .DiskMode ,
957+ Bus : controller .Bus ,
908958 }
909959 if backing .Datastore != nil {
910960 datastoreId , _ := sanitize (backing .Datastore .Value )
@@ -916,13 +966,15 @@ func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
916966 disks = append (disks , md )
917967 case * types.VirtualDiskFlatVer2BackingInfo :
918968 md := model.Disk {
919- Key : disk .Key ,
920- File : backing .FileName ,
921- Capacity : disk .CapacityInBytes ,
922- Shared : backing .Sharing != "sharingNone" && backing .Sharing != "" ,
923- Mode : backing .DiskMode ,
924- Bus : controller .Bus ,
925- Serial : backing .Uuid ,
969+ Key : disk .Key ,
970+ UnitNumber : * disk .UnitNumber ,
971+ ControllerKey : disk .ControllerKey ,
972+ File : backing .FileName ,
973+ Capacity : disk .CapacityInBytes ,
974+ Shared : backing .Sharing != "sharingNone" && backing .Sharing != "" ,
975+ Mode : backing .DiskMode ,
976+ Bus : controller .Bus ,
977+ Serial : backing .Uuid ,
926978 }
927979 if backing .Datastore != nil {
928980 datastoreId , _ := sanitize (backing .Datastore .Value )
@@ -934,14 +986,16 @@ func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
934986 disks = append (disks , md )
935987 case * types.VirtualDiskRawDiskMappingVer1BackingInfo :
936988 md := model.Disk {
937- Key : disk .Key ,
938- File : backing .FileName ,
939- Capacity : disk .CapacityInBytes ,
940- Shared : backing .Sharing != "sharingNone" && backing .Sharing != "" ,
941- Mode : backing .DiskMode ,
942- RDM : true ,
943- Bus : controller .Bus ,
944- Serial : backing .Uuid ,
989+ Key : disk .Key ,
990+ UnitNumber : * disk .UnitNumber ,
991+ ControllerKey : disk .ControllerKey ,
992+ File : backing .FileName ,
993+ Capacity : disk .CapacityInBytes ,
994+ Shared : backing .Sharing != "sharingNone" && backing .Sharing != "" ,
995+ Mode : backing .DiskMode ,
996+ RDM : true ,
997+ Bus : controller .Bus ,
998+ Serial : backing .Uuid ,
945999 }
9461000 if backing .Datastore != nil {
9471001 datastoreId , _ := sanitize (backing .Datastore .Value )
@@ -953,12 +1007,14 @@ func (v *VmAdapter) updateDisks(devArray *types.ArrayOfVirtualDevice) {
9531007 disks = append (disks , md )
9541008 case * types.VirtualDiskRawDiskVer2BackingInfo :
9551009 md := model.Disk {
956- Key : disk .Key ,
957- File : backing .DescriptorFileName ,
958- Capacity : disk .CapacityInBytes ,
959- Shared : backing .Sharing != "sharingNone" && backing .Sharing != "" ,
960- RDM : true ,
961- Bus : controller .Bus ,
1010+ Key : disk .Key ,
1011+ UnitNumber : * disk .UnitNumber ,
1012+ ControllerKey : disk .ControllerKey ,
1013+ File : backing .DescriptorFileName ,
1014+ Capacity : disk .CapacityInBytes ,
1015+ Shared : backing .Sharing != "sharingNone" && backing .Sharing != "" ,
1016+ RDM : true ,
1017+ Bus : controller .Bus ,
9621018 }
9631019 disks = append (disks , md )
9641020 }
0 commit comments