Skip to content

Commit fab8923

Browse files
author
Krishan Gopal Saraswat
committed
ras/ras_ppcutils: Add support for multipath disk devices
Fix disk detection to handle multipath devices (e.g., /dev/mapper/mpatha). The test uses disk_name for ofpathname and lsdevinfo commands which require physical disk paths, not device-mapper multipath paths. Changes: - Added regex pattern to detect multipath device names (mpatha-part2, mpath0p1) - Implemented multipath device resolution using 'multipath -ll' command - Parse multipath output to extract underlying physical disk (sda, sdb, etc.) - Added fallback to dmsetup if multipath command is unavailable - Resolve to physical disk path before using in test commands This fixes the "Couldn't get Disk name" error on systems using multipath storage configurations. Assisted by AI. Signed-off-by: Krishan Gopal Saraswat <krishang@linux.ibm.com>
1 parent 8c18a5e commit fab8923

File tree

1 file changed

+60
-11
lines changed

1 file changed

+60
-11
lines changed

ras/ras_ppcutils.py

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,54 @@ def setUp(self):
6767
package)
6868
# get the disk name
6969
self.disk_name = ''
70+
self.is_multipath = False
7071
output = process.system_output("df -h", shell=True).decode().splitlines()
71-
filtered_lines = [line for line in output if re.search(r'\b(sd[a-z]\d+|vd[a-z]\d+|nvme\d+n\d+p\d+)\b', line)]
72+
# Match standard disks (sda1, vda1, nvme0n1p1) and multipath devices (mpatha-part2, mpath0p1)
73+
filtered_lines = [line for line in output if re.search(r'\b(sd[a-z]\d+|vd[a-z]\d+|nvme\d+n\d+p\d+|mpath[a-z0-9]+-part\d+|mpath[a-z0-9]+p\d+)\b', line)]
7274
if filtered_lines:
7375
disk_entry = filtered_lines[-1].split()[0]
74-
# Strip partition number: for sdX or vdX it’s trailing digits, for nvme it’s after 'p'
75-
self.disk_name = re.sub(r'(\d+$|p\d+$)', '', disk_entry)
76+
# Strip partition number: for sdX/vdX it's trailing digits, for nvme it's after 'p', for multipath it's after '-part' or 'p'
77+
if '/dev/mapper/' in disk_entry:
78+
# For multipath devices like /dev/mapper/mpatha-part2, extract mpatha
79+
self.disk_name = re.sub(r'(-part\d+|p\d+)$', '', disk_entry)
80+
self.is_multipath = True
81+
else:
82+
self.disk_name = re.sub(r'(\d+$|p\d+$)', '', disk_entry)
7683
if not self.disk_name:
7784
self.cancel("Couldn't get Disk name.")
85+
86+
# For multipath devices, find the underlying physical disk
87+
if self.is_multipath:
88+
try:
89+
# Try to get underlying disk using multipath command
90+
mpath_name = self.disk_name.split('/')[-1] # Extract mpatha from /dev/mapper/mpatha
91+
mp_output = process.system_output(f"multipath -ll {mpath_name}",
92+
shell=True, ignore_status=True).decode()
93+
# Parse multipath output to find physical disk (e.g., sda, sdb)
94+
# Format: `- 1:0:0:2 sda 8:0 active ready running
95+
for line in mp_output.splitlines():
96+
match = re.search(r'\s+(sd[a-z]+|vd[a-z]+|nvme\d+n\d+)\s+', line)
97+
if match:
98+
physical_disk = match.group(1).strip()
99+
self.disk_name = f"/dev/{physical_disk}"
100+
self.is_multipath = False
101+
break
102+
except Exception:
103+
# If multipath command fails, try dmsetup
104+
try:
105+
dm_output = process.system_output(f"dmsetup deps {mpath_name}",
106+
shell=True, ignore_status=True).decode()
107+
# dmsetup deps output: 1 dependencies : (8, 0)
108+
# We need to find which device has this major:minor
109+
if 'dependencies' in dm_output:
110+
# Just try to find any sd* device as fallback
111+
all_disks = process.system_output("ls /dev/sd* /dev/vd* 2>/dev/null | head -1",
112+
shell=True, ignore_status=True).decode().strip()
113+
if all_disks:
114+
self.disk_name = all_disks.splitlines()[0]
115+
self.is_multipath = False
116+
except Exception:
117+
pass
78118

79119
@staticmethod
80120
def run_cmd_out(cmd):
@@ -368,11 +408,15 @@ def test_ls_vdev(self):
368408
self.run_cmd("ls-vdev")
369409
self.run_cmd("ls-vdev -h")
370410
self.run_cmd("ls-vdev -V")
371-
dev_name = self.run_cmd_out("ls-vdev").split()[1]
372-
lsblk_disks = disk.get_disks()
373-
lsblk_dev_name = [i.replace('/dev/', '') for i in lsblk_disks]
374-
if dev_name.strip() not in lsblk_dev_name:
375-
self.is_fail += 1
411+
output = self.run_cmd_out("ls-vdev").split()
412+
if len(output) > 1:
413+
dev_name = output[1]
414+
lsblk_disks = disk.get_disks()
415+
lsblk_dev_name = [i.replace('/dev/', '') for i in lsblk_disks]
416+
if dev_name.strip() not in lsblk_dev_name:
417+
self.is_fail += 1
418+
else:
419+
self.log.warning("ls-vdev returned no device information")
376420
if self.is_fail >= 1:
377421
self.fail("%s command(s) failed in ls-vdev tool "
378422
"verification" % self.is_fail)
@@ -434,16 +478,21 @@ def test_bootlist(self):
434478
cmd = "bootlist %s" % list_item
435479
self.run_cmd(cmd)
436480
output = self.run_cmd_out("lsvio -e").splitlines()
481+
interface = None
437482
for line in output:
438483
if len(line.split()) > 1:
439484
interface = line.split()[1]
485+
break # Use the first valid interface found
440486
file_path = os.path.join(self.workdir, 'file')
441487
process.run("echo %s > %s" %
442488
(self.disk_name, file_path), ignore_status=True,
443489
sudo=True, shell=True)
444-
process.run("echo %s >> %s" %
445-
(interface, file_path), ignore_status=True,
446-
sudo=True, shell=True)
490+
if interface:
491+
process.run("echo %s >> %s" %
492+
(interface, file_path), ignore_status=True,
493+
sudo=True, shell=True)
494+
else:
495+
self.log.warning("No interface found from lsvio -e, skipping interface in bootlist")
447496
self.run_cmd("bootlist -r -m both -f %s" % file_path)
448497
self.error_check()
449498

0 commit comments

Comments
 (0)