From 6032ec0515878db48803685639ba4966d12bb4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20=C5=A0imon?= Date: Fri, 15 Feb 2019 13:54:11 +0100 Subject: [PATCH] add default cluster cpu model --- pkg/virt-api/api.go | 4 +- .../mutating-webhook/mutating-webhook.go | 2 + .../mutating-webhook/mutating-webhook_test.go | 3 +- .../webhooks/mutating-webhook/preset.go | 25 ++++++- .../webhooks/mutating-webhook/preset_test.go | 67 +++++++++++++++++++ pkg/virt-api/webhooks/utils.go | 2 + 6 files changed, 100 insertions(+), 3 deletions(-) diff --git a/pkg/virt-api/api.go b/pkg/virt-api/api.go index 94676bce16ef..d9e0f8228ea8 100644 --- a/pkg/virt-api/api.go +++ b/pkg/virt-api/api.go @@ -1013,11 +1013,13 @@ func (app *virtAPIApp) Run() { go webhookInformers.VMIInformer.Run(stopChan) go webhookInformers.VMIPresetInformer.Run(stopChan) go webhookInformers.NamespaceLimitsInformer.Run(stopChan) + go webhookInformers.ConfigMapInformer.Run(stopChan) cache.WaitForCacheSync(stopChan, webhookInformers.VMIInformer.HasSynced, webhookInformers.VMIPresetInformer.HasSynced, - webhookInformers.NamespaceLimitsInformer.HasSynced) + webhookInformers.NamespaceLimitsInformer.HasSynced, + webhookInformers.ConfigMapInformer.HasSynced) // Verify/create webhook endpoint. err = app.createWebhook() diff --git a/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook.go b/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook.go index c9894caa5b6e..e34fb9db827c 100644 --- a/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook.go +++ b/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook.go @@ -105,6 +105,8 @@ func mutateVMIs(ar *v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { }, } } + // Apply default cpu model + setDefaultCPUModel(&vmi, informers.ConfigMapInformer.GetStore()) // Apply namespace limits applyNamespaceLimitRangeValues(&vmi, informers.NamespaceLimitsInformer) diff --git a/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook_test.go b/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook_test.go index ff707c414b37..5c823fd5f31f 100644 --- a/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook_test.go +++ b/pkg/virt-api/webhooks/mutating-webhook/mutating-webhook_test.go @@ -123,11 +123,12 @@ var _ = Describe("Mutating Webhook", func() { } namespaceLimitInformer, _ = testutils.NewFakeInformerFor(&k8sv1.LimitRange{}) namespaceLimitInformer.GetIndexer().Add(namespaceLimit) - + configMapInformer, _ := testutils.NewFakeInformerFor(&k8sv1.ConfigMap{}) webhooks.SetInformers( &webhooks.Informers{ VMIPresetInformer: presetInformer, NamespaceLimitsInformer: namespaceLimitInformer, + ConfigMapInformer: configMapInformer, }, ) }) diff --git a/pkg/virt-api/webhooks/mutating-webhook/preset.go b/pkg/virt-api/webhooks/mutating-webhook/preset.go index f4c5506f4a9c..da05cba64f51 100644 --- a/pkg/virt-api/webhooks/mutating-webhook/preset.go +++ b/pkg/virt-api/webhooks/mutating-webhook/preset.go @@ -33,7 +33,12 @@ import ( "kubevirt.io/kubevirt/pkg/log" ) -const exclusionMarking = "virtualmachineinstancepresets.admission.kubevirt.io/exclude" +const ( + exclusionMarking = "virtualmachineinstancepresets.admission.kubevirt.io/exclude" + namespaceKubevirt = "kubevirt" + configMapName = "kubevirt-config" + defaultCPUModelKey = "default-cpu-model" +) // listPresets returns all VirtualMachinePresets by namespace func listPresets(vmiPresetInformer cache.SharedIndexInformer, namespace string) ([]kubev1.VirtualMachineInstancePreset, error) { @@ -275,3 +280,21 @@ func isVMIExcluded(vmi *kubev1.VirtualMachineInstance) bool { } return false } + +//setDefaultCPUModel sets default cpu model from config if vmi doesn't have cpu model +func setDefaultCPUModel(vmi *kubev1.VirtualMachineInstance, configMapStore cache.Store) { + //if vmi doesn't have cpu topology or cpu model set + if vmi.Spec.Domain.CPU == nil || vmi.Spec.Domain.CPU.Model == "" { + // if default cluster cpu model is defined + if obj, exists, err := configMapStore.GetByKey(namespaceKubevirt + "/" + configMapName); err == nil && exists { + if obj.(*k8sv1.ConfigMap).Data[defaultCPUModelKey] != "" { + // create cpu topology struct + if vmi.Spec.Domain.CPU == nil { + vmi.Spec.Domain.CPU = &kubev1.CPU{} + } + //set is as vmi cpu model + vmi.Spec.Domain.CPU.Model = obj.(*k8sv1.ConfigMap).Data[defaultCPUModelKey] + } + } + } +} diff --git a/pkg/virt-api/webhooks/mutating-webhook/preset_test.go b/pkg/virt-api/webhooks/mutating-webhook/preset_test.go index 3699dcbc24b2..616c33c5f059 100644 --- a/pkg/virt-api/webhooks/mutating-webhook/preset_test.go +++ b/pkg/virt-api/webhooks/mutating-webhook/preset_test.go @@ -27,6 +27,7 @@ import ( k8sv1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/cache" @@ -518,6 +519,72 @@ var _ = Describe("Mutating Webhook Presets", func() { }) }) + Context("Apply default cpu model", func() { + var vmi v1.VirtualMachineInstance + var configMapIndexer cache.Indexer + var defaultCPUModel = "Haswell" + var cfgMap k8sv1.ConfigMap + + BeforeEach(func() { + configMapIndexer = cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, nil) + vmi = v1.VirtualMachineInstance{Spec: v1.VirtualMachineInstanceSpec{Domain: v1.DomainSpec{}}} + }) + + It("Should set default cpu model when vmi doesn't have it", func() { + cfgMap = k8sv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "kubevirt", + Name: "kubevirt-config", + }, + Data: map[string]string{ + defaultCPUModelKey: defaultCPUModel, + }, + } + configMapIndexer.Add(&cfgMap) + setDefaultCPUModel(&vmi, configMapIndexer) + + Expect(vmi.Spec.Domain.CPU).ToNot(BeNil()) + Expect(vmi.Spec.Domain.CPU.Model).To(Equal(defaultCPUModel)) + }) + + It("Should not set default cpu model when vmi does have it", func() { + cfgMap = k8sv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "kubevirt", + Name: "kubevirt-config", + }, + Data: map[string]string{ + defaultCPUModelKey: defaultCPUModel, + }, + } + configMapIndexer.Add(&cfgMap) + + vmCPUModel := "EPYC" + vmi.Spec.Domain.CPU = &v1.CPU{ + Model: vmCPUModel, + } + setDefaultCPUModel(&vmi, configMapIndexer) + + Expect(vmi.Spec.Domain.CPU).ToNot(BeNil()) + Expect(vmi.Spec.Domain.CPU.Model).To(Equal(vmCPUModel)) + }) + + It("Should has empty cpu model when cpu model is not set", func() { + cfgMap = k8sv1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "kubevirt", + Name: "kubevirt-config", + }, + Data: map[string]string{}, + } + configMapIndexer.Add(&cfgMap) + vmi.Spec.Domain.CPU = &v1.CPU{} + setDefaultCPUModel(&vmi, configMapIndexer) + Expect(vmi.Spec.Domain.CPU).ToNot(BeNil()) + Expect(vmi.Spec.Domain.CPU.Model).To(BeEmpty()) + }) + }) + Context("Apply Presets", func() { var vmi v1.VirtualMachineInstance var preset *v1.VirtualMachineInstancePreset diff --git a/pkg/virt-api/webhooks/utils.go b/pkg/virt-api/webhooks/utils.go index 653000fce2b6..74e0ea2b6240 100644 --- a/pkg/virt-api/webhooks/utils.go +++ b/pkg/virt-api/webhooks/utils.go @@ -80,6 +80,7 @@ type Informers struct { VMIPresetInformer cache.SharedIndexInformer NamespaceLimitsInformer cache.SharedIndexInformer VMIInformer cache.SharedIndexInformer + ConfigMapInformer cache.SharedIndexInformer } func GetInformers() *Informers { @@ -110,6 +111,7 @@ func newInformers() *Informers { VMIInformer: kubeInformerFactory.VMI(), VMIPresetInformer: kubeInformerFactory.VirtualMachinePreset(), NamespaceLimitsInformer: kubeInformerFactory.LimitRanges(), + ConfigMapInformer: kubeInformerFactory.ConfigMap(), } }