Skip to content

Commit 93940a0

Browse files
committed
chore(migration): check migration with HT
Signed-off-by: Maksim Fedotov <maksim.fedotov@flant.com>
1 parent d13b6a1 commit 93940a0

2 files changed

Lines changed: 103 additions & 5 deletions

File tree

images/virtualization-artifact/pkg/controller/kvbuilder/kvvm.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const (
5050

5151
// GenericCPUModel specifies the base CPU model for Features and Discovery CPU model types.
5252
GenericCPUModel = "qemu64"
53+
HTCPUFeature = "ht"
5354

5455
MaxMemorySizeForHotplug = 256 * 1024 * 1024 * 1024 // 256 Gi (safely limit to not overlap somewhat conservative 38 bit physical address space)
5556
EnableMemoryHotplugThreshold = 1 * 1024 * 1024 * 1024 // 1 Gi (no hotplug for VMs with less than 1Gi)
@@ -164,25 +165,35 @@ func (b *KVVM) SetCPUModel(class *v1alpha2.VirtualMachineClass) error {
164165
cpu.Model = class.Spec.CPU.Model
165166
case v1alpha2.CPUTypeDiscovery, v1alpha2.CPUTypeFeatures:
166167
cpu.Model = GenericCPUModel
167-
l := len(class.Status.CpuFeatures.Enabled)
168-
features := make([]virtv1.CPUFeature, l, l+1)
168+
features := make([]virtv1.CPUFeature, 0, len(class.Status.CpuFeatures.Enabled)+2)
169169
hasSvm := false
170-
for i, feature := range class.Status.CpuFeatures.Enabled {
170+
hasVMX := false
171+
hasHT := false
172+
for _, feature := range class.Status.CpuFeatures.Enabled {
171173
policy := "require"
172174
if feature == "invtsc" {
173175
policy = "optional"
174176
}
175177
if feature == "svm" {
176178
hasSvm = true
177179
}
178-
features[i] = virtv1.CPUFeature{
180+
if feature == "vmx" {
181+
hasVMX = true
182+
}
183+
if feature == HTCPUFeature {
184+
hasHT = true
185+
}
186+
features = append(features, virtv1.CPUFeature{
179187
Name: feature,
180188
Policy: policy,
181-
}
189+
})
182190
}
183191
if !hasSvm {
184192
features = append(features, virtv1.CPUFeature{Name: "svm", Policy: "optional"})
185193
}
194+
if hasVMX && !hasHT {
195+
features = append(features, virtv1.CPUFeature{Name: HTCPUFeature, Policy: "optional"})
196+
}
186197
cpu.Features = features
187198
default:
188199
return fmt.Errorf("unexpected cpu type: %q", class.Spec.CPU.Type)

images/virtualization-artifact/pkg/controller/kvbuilder/kvvm_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
corev1 "k8s.io/api/core/v1"
2424
"k8s.io/apimachinery/pkg/types"
25+
virtv1 "kubevirt.io/api/core/v1"
2526

2627
"github.com/deckhouse/virtualization/api/core/v1alpha2"
2728
)
@@ -224,6 +225,92 @@ func TestApplyPVNodeAffinity(t *testing.T) {
224225
})
225226
}
226227

228+
func TestSetCPUModel(t *testing.T) {
229+
name := "test-name"
230+
namespace := "test-namespace"
231+
232+
t.Run("should add optional ht feature for intel x86 discovery cpu", func(t *testing.T) {
233+
builder := NewEmptyKVVM(types.NamespacedName{Name: name, Namespace: namespace}, KVVMOptions{})
234+
class := &v1alpha2.VirtualMachineClass{
235+
Spec: v1alpha2.VirtualMachineClassSpec{
236+
CPU: v1alpha2.CPU{Type: v1alpha2.CPUTypeDiscovery},
237+
},
238+
Status: v1alpha2.VirtualMachineClassStatus{
239+
CpuFeatures: v1alpha2.CpuFeatures{Enabled: []string{"vmx", "aes"}},
240+
},
241+
}
242+
243+
if err := builder.SetCPUModel(class); err != nil {
244+
t.Fatalf("SetCPUModel() failed: %v", err)
245+
}
246+
247+
features := builder.Resource.Spec.Template.Spec.Domain.CPU.Features
248+
if !containsCPUFeature(features, virtv1.CPUFeature{Name: HTCPUFeature, Policy: "optional"}) {
249+
t.Fatalf("expected optional ht feature to be added, got %#v", features)
250+
}
251+
})
252+
253+
t.Run("should not add ht feature for amd discovery cpu", func(t *testing.T) {
254+
builder := NewEmptyKVVM(types.NamespacedName{Name: name, Namespace: namespace}, KVVMOptions{})
255+
class := &v1alpha2.VirtualMachineClass{
256+
Spec: v1alpha2.VirtualMachineClassSpec{
257+
CPU: v1alpha2.CPU{Type: v1alpha2.CPUTypeDiscovery},
258+
},
259+
Status: v1alpha2.VirtualMachineClassStatus{
260+
CpuFeatures: v1alpha2.CpuFeatures{Enabled: []string{"svm", "aes"}},
261+
},
262+
}
263+
264+
if err := builder.SetCPUModel(class); err != nil {
265+
t.Fatalf("SetCPUModel() failed: %v", err)
266+
}
267+
268+
features := builder.Resource.Spec.Template.Spec.Domain.CPU.Features
269+
if containsCPUFeature(features, virtv1.CPUFeature{Name: HTCPUFeature, Policy: "optional"}) {
270+
t.Fatalf("did not expect optional ht feature for amd cpu, got %#v", features)
271+
}
272+
})
273+
274+
t.Run("should keep existing ht feature policy when already present", func(t *testing.T) {
275+
builder := NewEmptyKVVM(types.NamespacedName{Name: name, Namespace: namespace}, KVVMOptions{})
276+
class := &v1alpha2.VirtualMachineClass{
277+
Spec: v1alpha2.VirtualMachineClassSpec{
278+
CPU: v1alpha2.CPU{Type: v1alpha2.CPUTypeFeatures},
279+
},
280+
Status: v1alpha2.VirtualMachineClassStatus{
281+
CpuFeatures: v1alpha2.CpuFeatures{Enabled: []string{"vmx", HTCPUFeature}},
282+
},
283+
}
284+
285+
if err := builder.SetCPUModel(class); err != nil {
286+
t.Fatalf("SetCPUModel() failed: %v", err)
287+
}
288+
289+
features := builder.Resource.Spec.Template.Spec.Domain.CPU.Features
290+
htCount := 0
291+
for _, feature := range features {
292+
if feature.Name == HTCPUFeature {
293+
htCount++
294+
if feature.Policy != "require" {
295+
t.Fatalf("expected existing ht policy to stay require, got %#v", feature)
296+
}
297+
}
298+
}
299+
if htCount != 1 {
300+
t.Fatalf("expected exactly one ht feature, got %#v", features)
301+
}
302+
})
303+
}
304+
305+
func containsCPUFeature(features []virtv1.CPUFeature, expected virtv1.CPUFeature) bool {
306+
for _, feature := range features {
307+
if feature == expected {
308+
return true
309+
}
310+
}
311+
return false
312+
}
313+
227314
func TestSetOsType(t *testing.T) {
228315
name := "test-name"
229316
namespace := "test-namespace"

0 commit comments

Comments
 (0)