Skip to content

Commit b040adb

Browse files
author
Roman Sysoev
committed
test(vm): add disk attachment test
Add new e2e test for hot attach/detach virtual disk to running VM. This test replaces the legacy vm_disk_attachment test with a more maintainable approach using object builders and framework helpers. - Remove legacy test with kustomize overlays - Add helper functions for VMBDA to legacy image_hotplug test - Remove vmDiskAttachment from test config Signed-off-by: Roman Sysoev <roman.sysoev@flant.com>
1 parent 32324ee commit b040adb

17 files changed

Lines changed: 260 additions & 492 deletions

File tree

test/e2e/default_config.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ testData:
2020
vmMigration: "/tmp/testdata/vm-migration"
2121
vmMigrationCancel: "/tmp/testdata/vm-migration-cancel"
2222
vmEvacuation: "/tmp/testdata/vm-evacuation"
23-
vmDiskAttachment: "/tmp/testdata/vm-disk-attachment"
2423
vmVersions: "/tmp/testdata/vm-versions"
2524
vdSnapshots: "/tmp/testdata/vd-snapshots"
2625
sshKey: "/tmp/testdata/sshkeys/id_ed"

test/e2e/internal/config/config.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ type TestData struct {
8888
VMMigration string `yaml:"vmMigration"`
8989
VMMigrationCancel string `yaml:"vmMigrationCancel"`
9090
VMEvacuation string `yaml:"vmEvacuation"`
91-
VMDiskAttachment string `yaml:"vmDiskAttachment"`
9291
VMVersions string `yaml:"vmVersions"`
9392
VdSnapshots string `yaml:"vdSnapshots"`
9493
Sshkey string `yaml:"sshKey"`

test/e2e/internal/util/block_device.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package util
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"errors"
2223
"fmt"
2324
"strings"
@@ -194,3 +195,34 @@ func GetExpectedDiskPhaseByVolumeBindingMode() string {
194195
return string(v1alpha2.DiskReady)
195196
}
196197
}
198+
199+
// GetDiskCount returns the number of block devices attached to a VM.
200+
// Uses lsblk --nodeps --json to get the list of block devices.
201+
func GetDiskCount(f *framework.Framework, vmName, vmNamespace string) (int, error) {
202+
cmd := "lsblk --nodeps --json"
203+
result, err := f.SSHCommand(vmName, vmNamespace, cmd)
204+
if err != nil {
205+
return 0, fmt.Errorf("failed to execute command: %w: %s", err, result)
206+
}
207+
208+
var disks Disks
209+
err = json.Unmarshal([]byte(result), &disks)
210+
if err != nil {
211+
return 0, fmt.Errorf("failed to parse lsblk output: %w", err)
212+
}
213+
214+
return len(disks.BlockDevices), nil
215+
}
216+
217+
// Disks represents the JSON output of lsblk --nodeps --json command.
218+
// It contains a list of block devices attached to the VM.
219+
type Disks struct {
220+
BlockDevices []BlockDevice `json:"blockdevices"`
221+
}
222+
223+
// BlockDevice represents a single block device in the lsblk JSON output.
224+
type BlockDevice struct {
225+
Name string `json:"name"`
226+
Size string `json:"size"`
227+
Type string `json:"type"`
228+
}

test/e2e/legacy/image_hotplug.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
. "github.com/onsi/ginkgo/v2"
2626
. "github.com/onsi/gomega"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2728
virtv1 "kubevirt.io/api/core/v1"
2829

2930
"github.com/deckhouse/virtualization/api/core/v1alpha2"
@@ -33,8 +34,13 @@ import (
3334
kc "github.com/deckhouse/virtualization/test/e2e/internal/kubectl"
3435
"github.com/deckhouse/virtualization/test/e2e/internal/label"
3536
"github.com/deckhouse/virtualization/test/e2e/internal/object"
37+
"github.com/deckhouse/virtualization/test/e2e/internal/util"
3638
)
3739

40+
const unacceptableCount = -1000
41+
42+
var APIVersion = v1alpha2.SchemeGroupVersion.String()
43+
3844
var _ = Describe("ImageHotplug", Ordered, label.Legacy(), func() {
3945
const (
4046
viCount = 2
@@ -336,3 +342,76 @@ func IsBlockDeviceReadOnly(vmNamespace, vmName, blockDeviceID string) (bool, err
336342
roOpt := options[0]
337343
return roOpt == "ro", nil
338344
}
345+
346+
// lsblk JSON output
347+
type Disks struct {
348+
BlockDevices []BlockDevice `json:"blockdevices"`
349+
}
350+
351+
type BlockDevices struct {
352+
BlockDevices []BlockDevice `json:"blockdevices"`
353+
}
354+
355+
type BlockDevice struct {
356+
Name string `json:"name"`
357+
Size string `json:"size"`
358+
Type string `json:"type"`
359+
}
360+
361+
func AttachBlockDevice(vmNamespace, vmName, blockDeviceName string, blockDeviceType v1alpha2.VMBDAObjectRefKind, labels map[string]string, testDataPath string) {
362+
vmbdaFilePath := fmt.Sprintf("%s/vmbda/%s.yaml", testDataPath, blockDeviceName)
363+
err := CreateVMBDAManifest(vmbdaFilePath, vmName, blockDeviceName, blockDeviceType, labels)
364+
Expect(err).NotTo(HaveOccurred(), "%v", err)
365+
366+
res := kubectl.Apply(kc.ApplyOptions{
367+
Filename: []string{vmbdaFilePath},
368+
FilenameOption: kc.Filename,
369+
Namespace: vmNamespace,
370+
})
371+
Expect(res.Error()).NotTo(HaveOccurred(), res.StdErr())
372+
}
373+
374+
func CreateVMBDAManifest(filePath, vmName, blockDeviceName string, blockDeviceType v1alpha2.VMBDAObjectRefKind, labels map[string]string) error {
375+
vmbda := &v1alpha2.VirtualMachineBlockDeviceAttachment{
376+
TypeMeta: metav1.TypeMeta{
377+
APIVersion: APIVersion,
378+
Kind: v1alpha2.VirtualMachineBlockDeviceAttachmentKind,
379+
},
380+
ObjectMeta: metav1.ObjectMeta{
381+
Name: blockDeviceName,
382+
Labels: labels,
383+
},
384+
Spec: v1alpha2.VirtualMachineBlockDeviceAttachmentSpec{
385+
VirtualMachineName: vmName,
386+
BlockDeviceRef: v1alpha2.VMBDAObjectRef{
387+
Kind: blockDeviceType,
388+
Name: blockDeviceName,
389+
},
390+
},
391+
}
392+
393+
err := util.WriteYamlObject(filePath, vmbda)
394+
if err != nil {
395+
return err
396+
}
397+
398+
return nil
399+
}
400+
401+
func GetDisksMetadata(vmNamespace, vmName string, disks *Disks) error {
402+
GinkgoHelper()
403+
cmd := "lsblk --nodeps --json"
404+
res := framework.GetClients().D8Virtualization().SSHCommand(vmName, cmd, d8.SSHOptions{
405+
Namespace: vmNamespace,
406+
Username: conf.TestData.SSHUser,
407+
IdentityFile: conf.TestData.Sshkey,
408+
})
409+
if res.Error() != nil {
410+
return fmt.Errorf("cmd: %s\nstderr: %s", res.GetCmd(), res.StdErr())
411+
}
412+
err := json.Unmarshal(res.StdOutBytes(), disks)
413+
if err != nil {
414+
return fmt.Errorf("failed when getting disk count\nvirtualMachine: %s/%s\nstderr: %s", vmNamespace, vmName, res.StdErr())
415+
}
416+
return nil
417+
}

test/e2e/legacy/testdata/vm-disk-attachment/base/cfg/cloudinit.yaml

Lines changed: 0 additions & 24 deletions
This file was deleted.

test/e2e/legacy/testdata/vm-disk-attachment/base/kustomization.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

test/e2e/legacy/testdata/vm-disk-attachment/base/transformer.yaml

Lines changed: 0 additions & 54 deletions
This file was deleted.

test/e2e/legacy/testdata/vm-disk-attachment/base/vd-root.yaml

Lines changed: 0 additions & 13 deletions
This file was deleted.

test/e2e/legacy/testdata/vm-disk-attachment/base/vm.yaml

Lines changed: 0 additions & 22 deletions
This file was deleted.

test/e2e/legacy/testdata/vm-disk-attachment/kustomization.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)