@@ -26,10 +26,20 @@ const (
2626 //VMUnFreezeCmd is the template for VM unfreeze command
2727 VMUnFreezeCmd = "/usr/bin/virt-freezer --unfreeze --name %s --namespace %s"
2828 // VMContainerName is the name of the container to use for freeze/thaw
29- VMContainerName = "compute"
30- VMPodSelectorCreatedByLabel = "kubevirt.io/created-by"
29+ VMContainerName = "compute"
30+ VMPodSelectorCreatedByLabel = "kubevirt.io/created-by"
31+ VMInstancetypeDefaultGroup = "instancetype.kubevirt.io"
32+ VMInstancetypeDefaultVersion = "v1beta1"
3133)
3234
35+ var VMResourceProcessMap = map [string ]func (kubevirtv1.VirtualMachine ) []storkapi.ObjectInfo {
36+ "PersistentVolumeClaim" : GetVMPersistentVolumeClaims ,
37+ "ConfigMap" : GetVMConfigMaps ,
38+ "Secret" : GetVMSecrets ,
39+ "VirtualMachinePreference" : GetVMPreference ,
40+ "VirtualMachineInstancetype" : GetVMInstanceType ,
41+ }
42+
3343// IsVirtualMachineRunning returns true if virtualMachine is in running state
3444func IsVirtualMachineRunning (vm kubevirtv1.VirtualMachine ) bool {
3545
@@ -50,58 +60,121 @@ func GetVMDataVolumes(vm kubevirtv1.VirtualMachine) []string {
5060}
5161
5262// GetVMPersistentVolumeClaims returns persistentVolumeClaim names used by the VMs
53- func GetVMPersistentVolumeClaims (vm kubevirtv1.VirtualMachine ) []string {
63+ func GetVMPersistentVolumeClaims (vm kubevirtv1.VirtualMachine ) []storkapi. ObjectInfo {
5464
5565 volList := vm .Spec .Template .Spec .Volumes
56- PVCList := make ([]string , 0 )
66+ getobjectinfo := func (secretName string ) storkapi.ObjectInfo {
67+ return storkapi.ObjectInfo {
68+ Name : secretName ,
69+ Namespace : vm .Namespace ,
70+ GroupVersionKind : metav1.GroupVersionKind {
71+ Group : "core" ,
72+ Version : "v1" ,
73+ Kind : "PersistentVolumeClaim" ,
74+ },
75+ }
76+ }
77+ PVCList := make ([]storkapi.ObjectInfo , 0 )
5778 for _ , vol := range volList {
5879 if vol .VolumeSource .PersistentVolumeClaim != nil {
59- PVCList = append (PVCList , vol .VolumeSource .PersistentVolumeClaim .ClaimName )
80+
81+ PVCList = append (PVCList , getobjectinfo (vol .PersistentVolumeClaim .ClaimName ))
6082 }
6183 // Add DataVolume name to the PVC list
6284 if vol .VolumeSource .DataVolume != nil {
63- PVCList = append (PVCList , vol .VolumeSource .DataVolume .Name )
85+ PVCList = append (PVCList , getobjectinfo ( vol .VolumeSource .DataVolume .Name ) )
6486 }
6587 }
6688 return PVCList
6789}
6890
91+ func GetVMInstanceType (vm kubevirtv1.VirtualMachine ) []storkapi.ObjectInfo {
92+ instanceType := vm .Spec .Instancetype
93+ objectInfos := make ([]storkapi.ObjectInfo , 0 )
94+ if instanceType != nil {
95+ // Skip if instanceType is VirtualMachineClusterInstancetype as this is not namespace scoped
96+ if instanceType .Kind != "" && instanceType .Kind != "VirtualMachineClusterInstancetype" {
97+ objectInfos = append (objectInfos , storkapi.ObjectInfo {
98+ Name : instanceType .GetName (),
99+ Namespace : vm .Namespace ,
100+ GroupVersionKind : metav1.GroupVersionKind {
101+ Group : VMInstancetypeDefaultGroup ,
102+ Version : VMInstancetypeDefaultVersion ,
103+ Kind : "VirtualMachineInstancetype" ,
104+ },
105+ })
106+ }
107+ }
108+ return objectInfos
109+ }
110+
111+ func GetVMPreference (vm kubevirtv1.VirtualMachine ) []storkapi.ObjectInfo {
112+ vmPrefs := vm .Spec .Preference
113+ objectInfos := make ([]storkapi.ObjectInfo , 0 )
114+ if vmPrefs != nil {
115+ // skip if kind is VirtualMachineClusterPreference as this is not namespace scoped
116+ if vmPrefs .Kind != "" && vmPrefs .Kind != "VirtualMachineClusterPreference" {
117+ objectInfos = append (objectInfos , storkapi.ObjectInfo {
118+ Name : vmPrefs .GetName (),
119+ Namespace : vm .Namespace ,
120+ GroupVersionKind : metav1.GroupVersionKind {
121+ Group : VMInstancetypeDefaultGroup ,
122+ Version : VMInstancetypeDefaultVersion ,
123+ Kind : "VirtualMachinePreference" ,
124+ },
125+ })
126+ }
127+ }
128+ return objectInfos
129+ }
130+
69131// GetVMSecrets returns references to secrets in all supported formats of VM configs
70- func GetVMSecrets (vm kubevirtv1.VirtualMachine ) []string {
132+ func GetVMSecrets (vm kubevirtv1.VirtualMachine ) []storkapi. ObjectInfo {
71133
134+ getobjectinfo := func (secretName string ) storkapi.ObjectInfo {
135+ return storkapi.ObjectInfo {
136+ Name : secretName ,
137+ Namespace : vm .Namespace ,
138+ GroupVersionKind : metav1.GroupVersionKind {
139+ Group : "core" ,
140+ Version : "v1" ,
141+ Kind : "Secret" ,
142+ },
143+ }
144+ }
72145 volList := vm .Spec .Template .Spec .Volumes
73- secretList := make ([]string , 0 )
146+ secretList := make ([]storkapi. ObjectInfo , 0 )
74147 for _ , vol := range volList {
75148 // secret as VolumeType
76149 if vol .VolumeSource .Secret != nil {
77- secretList = append (secretList , vol .Secret .SecretName )
150+ secretList = append (secretList , getobjectinfo ( vol .Secret .SecretName ) )
78151 }
79152 // Secret reference as sysprep
80153 if vol .VolumeSource .Sysprep != nil {
81154 if vol .VolumeSource .Sysprep .Secret != nil {
82- secretList = append (secretList , vol .VolumeSource .Sysprep .Secret .Name )
155+ secretList = append (secretList , getobjectinfo ( vol .VolumeSource .Sysprep .Secret .Name ) )
83156 }
84157 }
85158 if vol .VolumeSource .CloudInitNoCloud != nil {
86159 cloudInitNoCloud := vol .VolumeSource .CloudInitNoCloud
87160 // secret as NetworkDataSecretRef
88161 if cloudInitNoCloud .NetworkDataSecretRef != nil {
89- secretList = append (secretList , cloudInitNoCloud .NetworkDataSecretRef .Name )
162+ secretList = append (secretList , getobjectinfo ( cloudInitNoCloud .NetworkDataSecretRef .Name ) )
90163 }
91164 // secret as UserDataSecretRef
92165 if cloudInitNoCloud .UserDataSecretRef != nil {
93- secretList = append (secretList , cloudInitNoCloud .UserDataSecretRef .Name )
166+ secretList = append (secretList , getobjectinfo ( cloudInitNoCloud .UserDataSecretRef .Name ) )
94167 }
95168 }
96169 if vol .VolumeSource .CloudInitConfigDrive != nil {
97170 cloudInitConfigDrive := vol .VolumeSource .CloudInitConfigDrive
98171 // Secret from configDrive for NetworkData
99172 if cloudInitConfigDrive .NetworkDataSecretRef != nil {
100- secretList = append (secretList , cloudInitConfigDrive .NetworkDataSecretRef .Name )
173+ secretList = append (secretList , getobjectinfo ( cloudInitConfigDrive .NetworkDataSecretRef .Name ) )
101174 }
102175 // Secret from configDrive aka Ignition
103176 if cloudInitConfigDrive .UserDataSecretRef != nil {
104- secretList = append (secretList , cloudInitConfigDrive .UserDataSecretRef .Name )
177+ secretList = append (secretList , getobjectinfo ( cloudInitConfigDrive .UserDataSecretRef .Name ) )
105178 }
106179
107180 }
@@ -110,22 +183,33 @@ func GetVMSecrets(vm kubevirtv1.VirtualMachine) []string {
110183}
111184
112185// GetVMConfigMaps returns ConfigMaps referenced in the VirtualMachine.
113- func GetVMConfigMaps (vm kubevirtv1.VirtualMachine ) []string {
186+ func GetVMConfigMaps (vm kubevirtv1.VirtualMachine ) []storkapi.ObjectInfo {
187+
188+ getobjectinfo := func (configMapName string ) storkapi.ObjectInfo {
189+ return storkapi.ObjectInfo {
190+ Name : configMapName ,
191+ Namespace : vm .Namespace ,
192+ GroupVersionKind : metav1.GroupVersionKind {
193+ Group : "core" ,
194+ Version : "v1" ,
195+ Kind : "ConfigMap" ,
196+ },
197+ }
198+ }
114199
115200 volList := vm .Spec .Template .Spec .Volumes
116- configMaps := make ([]string , 0 )
201+ configMaps := make ([]storkapi. ObjectInfo , 0 )
117202 for _ , vol := range volList {
118203 // ConfigMap as volumeType
119204 if vol .ConfigMap != nil {
120- configMaps = append (configMaps , vol .ConfigMap .Name )
205+ configMaps = append (configMaps , getobjectinfo ( vol .ConfigMap .Name ) )
121206 }
122207 // configMap reference in sysprep
123208 if vol .VolumeSource .Sysprep != nil {
124209 if vol .VolumeSource .Sysprep .ConfigMap != nil {
125- configMaps = append (configMaps , vol .VolumeSource .Sysprep .ConfigMap .Name )
210+ configMaps = append (configMaps , getobjectinfo ( vol .VolumeSource .Sysprep .ConfigMap .Name ) )
126211 }
127212 }
128-
129213 }
130214 return configMaps
131215}
@@ -255,9 +339,19 @@ func (r *ResourceCollector) prepareVirtualMachineForApply(
255339
256340 // Transform dataVolume to associated PVC for dataVolumeTemplate configurations
257341 path = "spec.template.spec.volumes"
258- err := transformPath (object , strings .Split (path , "." ))
342+ if err := transformPath (object , strings .Split (path , "." )); err != nil {
343+ return err
344+ }
345+
346+ // remove revisionName from preference and instancetype
347+ content := object .UnstructuredContent ()
348+ pathD := []string {"spec" , "preference" , "revisionName" }
349+ unstructured .RemoveNestedField (content , pathD ... )
259350
260- return err
351+ pathD = []string {"spec" , "instancetype" , "revisionName" }
352+ unstructured .RemoveNestedField (content , pathD ... )
353+
354+ return nil
261355
262356}
263357
@@ -279,6 +373,7 @@ func (r *ResourceCollector) prepareVirtualMachineForCollection(
279373 // is not necessary
280374 path = []string {"spec" , "dataVolumeTemplates" }
281375 unstructured .RemoveNestedField (content , path ... )
376+
282377 return nil
283378}
284379
@@ -333,39 +428,15 @@ func GetVMResourcesFromResourceObject(objects []runtime.Unstructured,
333428func GetObjectInfoFromVMResources (vm kubevirtv1.VirtualMachine ) []storkapi.ObjectInfo {
334429
335430 vmResourceInfoList := make ([]storkapi.ObjectInfo , 0 )
336-
337- // get PVCs of the VM
338- volumeObjectInfoList := getObjectInfo (GetVMPersistentVolumeClaims (vm ), vm .Namespace , "PersistentVolumeClaim" )
339- vmResourceInfoList = append (vmResourceInfoList , volumeObjectInfoList ... )
340-
341- // get configMaps of the VM
342- configMapObjectInfoList := getObjectInfo (GetVMConfigMaps (vm ), vm .Namespace , "ConfigMap" )
343- vmResourceInfoList = append (vmResourceInfoList , configMapObjectInfoList ... )
344-
345- // getSecret references of the VM
346- secretObjectInfoList := getObjectInfo (GetVMSecrets (vm ), vm .Namespace , "Secret" )
347- vmResourceInfoList = append (vmResourceInfoList , secretObjectInfoList ... )
348-
349- return vmResourceInfoList
350-
351- }
352-
353- // getObjectInfo helper function that returns ObjectInfo object from resourcesName and namespace
354- func getObjectInfo (resourceNames []string , namespace string , objectKind string ) []storkapi.ObjectInfo {
355- objectInfoList := make ([]storkapi.ObjectInfo , 0 )
356- for _ , resource := range resourceNames {
357- info := storkapi.ObjectInfo {
358- GroupVersionKind : metav1.GroupVersionKind {
359- Group : "core" ,
360- Version : "v1" ,
361- Kind : objectKind ,
362- },
363- Name : resource ,
364- Namespace : namespace ,
431+ for vmResource , _ := range VMResourceProcessMap {
432+ if processFunc , ok := VMResourceProcessMap [vmResource ]; ok {
433+ logrus .Debugf ("fetching %v resources for vm %v" , vmResource , vm .Name )
434+ resourceInfoList := processFunc (vm )
435+ vmResourceInfoList = append (vmResourceInfoList , resourceInfoList ... )
365436 }
366- objectInfoList = append (objectInfoList , info )
367437 }
368- return objectInfoList
438+
439+ return vmResourceInfoList
369440
370441}
371442
@@ -578,3 +649,24 @@ func IsVmPresentInNS(ns string) bool {
578649 }
579650 return false
580651}
652+
653+ // For VMs dependent resources should be applied first before applying VM object. This function
654+ // moves VM object to last in the list of objects.
655+ func MoveVMObjectToLast (objects []runtime.Unstructured ) []runtime.Unstructured {
656+
657+ if len (objects ) == 0 {
658+ return objects
659+ }
660+ newObject := make ([]runtime.Unstructured , 0 )
661+ vmObject := make ([]runtime.Unstructured , 0 )
662+ for _ , o := range objects {
663+ if o .GetObjectKind ().GroupVersionKind ().Kind == "VirtualMachine" {
664+ vmObject = append (vmObject , o )
665+ continue
666+ }
667+ newObject = append (newObject , o )
668+ }
669+ newObject = append (newObject , vmObject ... )
670+ return newObject
671+
672+ }
0 commit comments