Skip to content

Commit f20f85e

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. Signed-off-by: Jathavedhan M <jathavedhan.m@ibm.com>
1 parent 2d5dcfc commit f20f85e

File tree

6 files changed

+71
-12
lines changed

6 files changed

+71
-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"
@@ -38,6 +39,7 @@ const (
3839
backupNamespaceEnv = "KVP_BACKUP_NS"
3940
regionEnv = "KVP_REGION"
4041
storageClassEnv = "KVP_STORAGE_CLASS"
42+
defaultMachineTypeEnv = "KVP_DEFAULT_MACHINE_TYPE"
4143

4244
defaultRegionName = "minio"
4345
defaultBackupNamespace = "velero"
@@ -49,6 +51,7 @@ var (
4951
ClientsInstance = &Clients{}
5052
BackupScriptInstance = &BackupScript{}
5153
reporter = NewKubernetesReporter()
54+
DefaultMachineType = "q35"
5255
)
5356

5457
// Framework supports common operations used by functional/e2e tests. It holds the k8s and cdi clients,
@@ -746,3 +749,58 @@ func GetKubevirt(kvClient kubecli.KubevirtClient) *kv1.KubeVirt {
746749
gomega.Expect(kvList.Items).To(gomega.HaveLen(1))
747750
return &kvList.Items[0]
748751
}
752+
753+
// InitDefaultMachineType sets DefaultMachineType from KVP_DEFAULT_MACHINE_TYPE or from worker node
754+
// architecture (first schedulable node with arch, else any node; see also Status.NodeInfo and label kubernetes.io/arch).
755+
func InitDefaultMachineType(client kubernetes.Interface) {
756+
if v := strings.TrimSpace(os.Getenv(defaultMachineTypeEnv)); v != "" {
757+
DefaultMachineType = v
758+
fmt.Fprintf(ginkgo.GinkgoWriter, "DefaultMachineType (from %s env): %s\n", defaultMachineTypeEnv, DefaultMachineType)
759+
return
760+
}
761+
arch, err := detectClusterArchitecture(client)
762+
if err != nil {
763+
fmt.Fprintf(ginkgo.GinkgoWriter, "WARNING: failed to detect cluster architecture, defaulting to %s: %v\n", DefaultMachineType, err)
764+
return
765+
}
766+
switch arch {
767+
case "s390x":
768+
DefaultMachineType = "s390-ccw-virtio"
769+
case "arm64":
770+
DefaultMachineType = "virt"
771+
default:
772+
DefaultMachineType = "q35"
773+
}
774+
fmt.Fprintf(ginkgo.GinkgoWriter, "DefaultMachineType (detected arch %s): %s\n", arch, DefaultMachineType)
775+
}
776+
777+
func detectClusterArchitecture(client kubernetes.Interface) (string, error) {
778+
nl, err := client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{Limit: 500})
779+
if err != nil {
780+
return "", err
781+
}
782+
if len(nl.Items) == 0 {
783+
return "", fmt.Errorf("no nodes in cluster")
784+
}
785+
var fallback string
786+
for i := range nl.Items {
787+
n := &nl.Items[i]
788+
arch := strings.TrimSpace(n.Status.NodeInfo.Architecture)
789+
if arch == "" {
790+
arch = strings.TrimSpace(n.Labels[v1.LabelArchStable])
791+
}
792+
if arch == "" {
793+
continue
794+
}
795+
if !n.Spec.Unschedulable {
796+
return arch, nil
797+
}
798+
if fallback == "" {
799+
fallback = arch
800+
}
801+
}
802+
if fallback != "" {
803+
return fallback, nil
804+
}
805+
return "", fmt.Errorf("no node reports architecture")
806+
}

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
@@ -127,7 +127,7 @@ version: 2`
127127
},
128128
},
129129
Machine: &v1.Machine{
130-
Type: "q35",
130+
Type: DefaultMachineType,
131131
},
132132
Devices: v1.Devices{
133133
Rng: &v1.Rng{},

tests/tests_suite_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func BuildTestSuite() {
6868
}
6969
framework.ClientsInstance.K8sClient = k8sClient
7070

71+
framework.InitDefaultMachineType(k8sClient)
7172
listPlugins()
7273
})
7374

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)