Skip to content

Commit c5b77b4

Browse files
committed
PB-8121 kubevirt support for vmInstancetype and vmPreference
Signed-off-by: vsundarraj-px <[email protected]>
1 parent 9528b1f commit c5b77b4

File tree

2 files changed

+148
-53
lines changed

2 files changed

+148
-53
lines changed

pkg/applicationmanager/controllers/applicationrestore.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1729,7 +1729,8 @@ func (a *ApplicationRestoreController) applyResources(
17291729
return err
17301730
}
17311731
}
1732-
1732+
// Move VM object to last so that dependent objects are applied first.
1733+
objects = resourcecollector.MoveVMObjectToLast(objects)
17331734
restore.Status.ResourceCount = len(objects)
17341735
tempResourceList := make([]*storkapi.ApplicationRestoreResourceInfo, 0)
17351736
for _, o := range objects {
@@ -1779,6 +1780,7 @@ func (a *ApplicationRestoreController) applyResources(
17791780
}
17801781
}
17811782
if err != nil {
1783+
logrus.Debugf("error applying resource %v", err)
17821784
if tempResourceList, err = a.updateResourceStatus(
17831785
restore,
17841786
o,
@@ -1789,6 +1791,7 @@ func (a *ApplicationRestoreController) applyResources(
17891791
return err
17901792
}
17911793
} else if retained {
1794+
logrus.Debugf("error applying resource %v", err)
17921795
if tempResourceList, err = a.updateResourceStatus(
17931796
restore,
17941797
o,

pkg/resourcecollector/virtualmachine.go

Lines changed: 144 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -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
3444
func 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,
333428
func 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

Comments
 (0)