Skip to content

Commit 36a10de

Browse files
committed
tests: add multipath.single-disk to verify that multipath can be
reduced to one path Reduce disk on multipath via qmp, then reboot. `{ "execute": "device_del", "arguments": { "id": "/machine/peripheral-anon/device[3]"}}` See https://issues.redhat.com/browse/OCPBUGS-56597
1 parent 82410e1 commit 36a10de

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

mantle/kola/tests/misc/multipath.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package misc
1616

1717
import (
1818
"fmt"
19+
"strconv"
1920
"strings"
2021
"time"
2122

@@ -103,6 +104,13 @@ systemd:
103104
104105
[Install]
105106
WantedBy=multi-user.target`)
107+
108+
mpath_single_disk = conf.Butane(`
109+
variant: fcos
110+
version: 1.6.0
111+
kernel_arguments:
112+
should_exist:
113+
- rd.multipath=default`)
106114
)
107115

108116
func init() {
@@ -132,6 +140,16 @@ func init() {
132140
UserData: mpath_on_var_lib_containers,
133141
AdditionalDisks: []string{"1G:mpath,wwn=1"},
134142
})
143+
// See https://issues.redhat.com/browse/OCPBUGS-56597
144+
register.RegisterTest(&register.Test{
145+
Name: "multipath.single-disk",
146+
Description: "Verify that multipath can be reduced to one path",
147+
Run: runMultipathReduceDisk,
148+
ClusterSize: 1,
149+
Platforms: []string{"qemu"},
150+
UserData: mpath_single_disk,
151+
MultiPathDisk: true,
152+
})
135153
}
136154

137155
func verifyMultipathBoot(c cluster.TestCluster, m platform.Machine) {
@@ -223,3 +241,37 @@ func waitForCompleteFirstboot(c cluster.TestCluster) {
223241
c.Fatalf("Timed out while waiting for first-boot-complete.target to be ready: %v", err)
224242
}
225243
}
244+
245+
func verifyMultipathDisks(c cluster.TestCluster, m platform.Machine, expect int) {
246+
device := strings.TrimSpace(string(c.MustSSH(m, "sudo multipath -l -v 1")))
247+
if device == "" {
248+
c.Fatalf("Failed to find multipath device")
249+
}
250+
output := string(c.MustSSHf(m, "lsblk --pairs --paths --inverse --output NAME /dev/mapper/%s | grep -v /dev/mapper | wc -l", device))
251+
count, err := strconv.Atoi(strings.TrimSpace(output))
252+
if err != nil {
253+
c.Fatalf("Failed to parse device count: %v", err)
254+
}
255+
256+
if count != expect {
257+
c.Fatalf("Expected %d multipath devices, but found %d", expect, count)
258+
}
259+
}
260+
261+
func runMultipathReduceDisk(c cluster.TestCluster) {
262+
m := c.Machines()[0]
263+
verifyMultipathBoot(c, m)
264+
// wait until first-boot-complete.target is reached
265+
waitForCompleteFirstboot(c)
266+
verifyMultipathDisks(c, m, 2)
267+
268+
if err := m.(platform.QEMUMachine).RemoveBlockDeviceForMultipath("mpath11"); err != nil {
269+
c.Fatalf("failed to reduce multipath disk: %v", err)
270+
}
271+
272+
if err := m.Reboot(); err != nil {
273+
c.Fatalf("Failed to reboot the machine: %v", err)
274+
}
275+
verifyMultipathDisks(c, m, 1)
276+
c.RunCmdSync(m, "grep mpath.wwid= /proc/cmdline")
277+
}

mantle/platform/machine/qemu/machine.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,7 @@ func (m *machine) JournalOutput() string {
124124
func (m *machine) RemovePrimaryBlockDevice() error {
125125
return m.inst.RemovePrimaryBlockDevice()
126126
}
127+
128+
func (m *machine) RemoveBlockDeviceForMultipath(device string) error {
129+
return m.inst.RemoveBlockDeviceForMultipath(device)
130+
}

mantle/platform/qemu.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type QEMUMachine interface {
8585
// RemovePrimaryBlockDevice removes the primary device from a given qemu
8686
// instance and sets the secondary device as primary.
8787
RemovePrimaryBlockDevice() error
88+
RemoveBlockDeviceForMultipath(device string) error
8889
}
8990

9091
// Disk holds the details of a virtual disk.
@@ -445,6 +446,32 @@ func (inst *QemuInstance) RemovePrimaryBlockDevice() (err2 error) {
445446
return nil
446447
}
447448

449+
// RemoveBlockDeviceForMultipath remove the specified device on multipath.
450+
func (inst *QemuInstance) RemoveBlockDeviceForMultipath(device string) error {
451+
blkdevs, err := inst.listBlkDevices()
452+
if err != nil {
453+
return errors.Wrapf(err, "Could not list block devices through qmp")
454+
}
455+
456+
var devicePath string
457+
for _, dev := range blkdevs.Return {
458+
if dev.Device == device {
459+
devicePath = dev.DevicePath
460+
break
461+
}
462+
}
463+
464+
if devicePath == "" {
465+
return fmt.Errorf("Target device %q not found in block device list", devicePath)
466+
}
467+
468+
if err = inst.deleteBlockDevice(devicePath); err != nil {
469+
return errors.Wrapf(err, "Could not delete device %v", devicePath)
470+
}
471+
472+
return nil
473+
}
474+
448475
// A directory mounted from the host into the guest, via 9p or virtiofs
449476
type HostMount struct {
450477
src string

0 commit comments

Comments
 (0)