Skip to content

Commit 9bac35d

Browse files
committed
Allow VM machine type to be set dynamically
This change removes the hardcoded VM machine type and replaces it with a configurable default. A new initialization step determines the machine type based on an environment variable, falling back to the system architecture when not explicitly set. VM creation paths have been updated to consistently use this default, ensuring behavior is uniform across tests. YAML generation has also been adjusted to dynamically inject the selected machine type, avoiding duplication and making configurations easier to override.
1 parent 595cf41 commit 9bac35d

File tree

6 files changed

+72
-12
lines changed

6 files changed

+72
-12
lines changed

tests/framework/framework.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"path/filepath"
1010
"sort"
1111
"strconv"
12+
"strings"
1213
"time"
1314

1415
ginkgo "github.com/onsi/ginkgo/v2"
@@ -36,6 +37,7 @@ const (
3637
backupNamespaceEnv = "KVP_BACKUP_NS"
3738
regionEnv = "KVP_REGION"
3839
storageClassEnv = "KVP_STORAGE_CLASS"
40+
defaultMachineTypeEnv = "KVP_DEFAULT_MACHINE_TYPE"
3941

4042
defaultRegionName = "minio"
4143
defaultBackupNamespace = "velero"
@@ -47,6 +49,7 @@ var (
4749
ClientsInstance = &Clients{}
4850
BackupScriptInstance = &BackupScript{}
4951
reporter = NewKubernetesReporter()
52+
DefaultMachineType = "q35"
5053
)
5154

5255
// Framework supports common operations used by functional/e2e tests. It holds the k8s and cdi clients,
@@ -516,3 +519,58 @@ func GetKubevirt(kvClient kubecli.KubevirtClient) *kv1.KubeVirt {
516519
gomega.Expect(kvList.Items).To(gomega.HaveLen(1))
517520
return &kvList.Items[0]
518521
}
522+
523+
// InitDefaultMachineType sets DefaultMachineType from KVP_DEFAULT_MACHINE_TYPE or from worker node
524+
// architecture (first schedulable node with arch, else any node; see also Status.NodeInfo and label kubernetes.io/arch).
525+
func InitDefaultMachineType(client kubernetes.Interface) {
526+
if v := strings.TrimSpace(os.Getenv(defaultMachineTypeEnv)); v != "" {
527+
DefaultMachineType = v
528+
fmt.Fprintf(ginkgo.GinkgoWriter, "DefaultMachineType (from %s env): %s\n", defaultMachineTypeEnv, DefaultMachineType)
529+
return
530+
}
531+
arch, err := detectClusterArchitecture(client)
532+
if err != nil {
533+
fmt.Fprintf(ginkgo.GinkgoWriter, "WARNING: failed to detect cluster architecture, defaulting to %s: %v\n", DefaultMachineType, err)
534+
return
535+
}
536+
switch arch {
537+
case "s390x":
538+
DefaultMachineType = "s390-ccw-virtio"
539+
case "arm64":
540+
DefaultMachineType = "virt"
541+
default:
542+
DefaultMachineType = "q35"
543+
}
544+
fmt.Fprintf(ginkgo.GinkgoWriter, "DefaultMachineType (detected arch %s): %s\n", arch, DefaultMachineType)
545+
}
546+
547+
func detectClusterArchitecture(client kubernetes.Interface) (string, error) {
548+
nl, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{Limit: 500})
549+
if err != nil {
550+
return "", err
551+
}
552+
if len(nl.Items) == 0 {
553+
return "", fmt.Errorf("no nodes in cluster")
554+
}
555+
var fallback string
556+
for i := range nl.Items {
557+
n := &nl.Items[i]
558+
arch := strings.TrimSpace(n.Status.NodeInfo.Architecture)
559+
if arch == "" {
560+
arch = strings.TrimSpace(n.Labels[v1.LabelArchStable])
561+
}
562+
if arch == "" {
563+
continue
564+
}
565+
if !n.Spec.Unschedulable {
566+
return arch, nil
567+
}
568+
if fallback == "" {
569+
fallback = arch
570+
}
571+
}
572+
if fallback != "" {
573+
return fallback, nil
574+
}
575+
return "", fmt.Errorf("no node reports architecture")
576+
}

tests/framework/kubectl.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ func (f *Framework) CreateKubectlCommand(args ...string) *exec.Cmd {
3333
return cmd
3434
}
3535

36-
// RunKubectlCreateYamlCommand replaces storageclassname placeholder with configured tests storageClass
37-
// in a given yaml, creates it and returns err
36+
// RunKubectlCreateYamlCommand substitutes {{KVP_STORAGE_CLASS}} and spec.domain.machine.type (template uses q35), then kubectl create.
3837
func (f *Framework) RunKubectlCreateYamlCommand(yamlPath string) error {
3938
kubeconfig := f.KubeConfig
4039
path := f.KubectlPath
4140
storageClass := f.StorageClass
42-
43-
cmdString := fmt.Sprintf("cat %s | sed 's/{{KVP_STORAGE_CLASS}}/%s/g' | %s create -n %s -f -", yamlPath, storageClass, path, f.Namespace.Name)
41+
cmdString := fmt.Sprintf(
42+
"cat %s | sed 's|{{KVP_STORAGE_CLASS}}|%s|g' | sed 's|type: q35|type: %s|g' | %s create -n %s -f -",
43+
yamlPath, storageClass, DefaultMachineType, path, f.Namespace.Name,
44+
)
4445
cmd := exec.Command("bash", "-c", cmdString)
4546
kubeconfEnv := fmt.Sprintf("KUBECONFIG=%s", kubeconfig)
4647
cmd.Env = append(os.Environ(), kubeconfEnv)

tests/framework/manifests_utils.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ func (f *Framework) CreateVMWithDVAndDVTemplate() error {
7676
}
7777

7878
func (f *Framework) CreateVMWithPVC() error {
79-
err := f.RunKubectlCommand("create", "-f", "manifests/vm_with_pvc.yaml", "-n", f.Namespace.Name)
80-
return err
79+
return f.RunKubectlCreateYamlCommand("manifests/vm_with_pvc.yaml")
8180
}
8281

8382
func (f *Framework) CreateVMForHotplug() error {
@@ -86,6 +85,5 @@ func (f *Framework) CreateVMForHotplug() error {
8685
}
8786

8887
func (f *Framework) CreateVMIWithDataVolume() error {
89-
err := f.RunKubectlCommand("create", "-f", "manifests/vmi_with_dv.yaml", "-n", f.Namespace.Name)
90-
return err
88+
return f.RunKubectlCreateYamlCommand("manifests/vmi_with_dv.yaml")
9189
}

tests/framework/vm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ version: 2`
126126
},
127127
},
128128
Machine: &v1.Machine{
129-
Type: "q35",
129+
Type: DefaultMachineType,
130130
},
131131
Devices: v1.Devices{
132132
Rng: &v1.Rng{},

tests/tests_suite_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ func BuildTestSuite() {
6565
Fail(fmt.Sprintf("ERROR, unable to create K8sClient: %v", err))
6666
}
6767
framework.ClientsInstance.K8sClient = k8sClient
68+
69+
framework.InitDefaultMachineType(k8sClient)
6870
})
6971

7072
AfterSuite(func() {

tests/utils.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
kvv1 "kubevirt.io/api/core/v1"
1515
"kubevirt.io/client-go/kubecli"
1616
cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
17+
"kubevirt.io/kubevirt-velero-plugin/tests/framework"
1718
)
1819

1920
const (
@@ -60,7 +61,7 @@ var newVMSpecBlankDVTemplate = func(vmName, size string) *kvv1.VirtualMachine {
6061
},
6162
},
6263
Machine: &kvv1.Machine{
63-
Type: "",
64+
Type: framework.DefaultMachineType,
6465
},
6566
Devices: kvv1.Devices{
6667
Disks: []kvv1.Disk{
@@ -132,7 +133,7 @@ var newVMSpec = func(vmName, size string, volumeSource kvv1.VolumeSource) *kvv1.
132133
},
133134
},
134135
Machine: &kvv1.Machine{
135-
Type: "",
136+
Type: framework.DefaultMachineType,
136137
},
137138
Devices: kvv1.Devices{
138139
Disks: []kvv1.Disk{
@@ -191,7 +192,7 @@ func newVMISpec(vmiName string) *kvv1.VirtualMachineInstance {
191192
},
192193
},
193194
Machine: &kvv1.Machine{
194-
Type: "q35",
195+
Type: framework.DefaultMachineType,
195196
},
196197
Devices: kvv1.Devices{
197198
Rng: &kvv1.Rng{},

0 commit comments

Comments
 (0)