Created
January 17, 2026 17:59
-
-
Save nijave/fc9c60181db2ae621fe0ead273b5ff68 to your computer and use it in GitHub Desktop.
Print out disk information for zpool disks attached to a SAS3 controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Usage: sas3-table.py <controller #> | |
| Takes <controller #> like you'd pass to sas3ircu | |
| Requires | |
| - sas3ircu (assumes passwordless sudo) | |
| - lsblk | |
| - zpool (with --json flag) | |
| """ | |
| import json | |
| import shutil | |
| import sys | |
| import subprocess | |
| def dev_to_disk(path: str) -> str: | |
| lsblk = json.loads(subprocess.check_output(["lsblk", "--json", "-nlo", "TYPE,NAME,PKNAME", path], text=True)) | |
| dev_from_part = [item["pkname"] for item in lsblk["blockdevices"] if item["pkname"]] | |
| # if there's no partitions, there _should_ be a single disk item | |
| if not dev_from_part: | |
| return lsblk["blockdevices"][0]["name"] | |
| return dev_from_part[0] | |
| devices_output = subprocess.check_output( | |
| ["sudo", shutil.which("sas3ircu"), str(sys.argv[1]), "display"], | |
| text=True, | |
| ).strip() | |
| device = {} | |
| devices = [] | |
| in_device = False | |
| for line in devices_output.splitlines(): | |
| if line.startswith("Device is a Hard disk"): | |
| in_device = True | |
| continue | |
| if in_device and not line.startswith(" "): | |
| in_device = False | |
| if device: | |
| devices.append(device) | |
| device = {} | |
| if in_device: | |
| # print(line) | |
| device[line.split(":", 1)[0].strip()] = line.split(":", 1)[1].strip() | |
| for d in devices: | |
| d['Enclosure #'] = int(d['Enclosure #']) | |
| d['Slot #'] = int(d['Slot #']) | |
| zfs_devices = {} | |
| zpool_status = json.loads(subprocess.check_output(["zpool", "status", "-j"], text=True)) | |
| for pool, details in zpool_status['pools'].items(): | |
| vdevs = details['vdevs'][pool]['vdevs'] | |
| for zdev in vdevs.values(): | |
| for disk in zdev['vdevs'].values(): | |
| dev = dev_to_disk(disk['path']) | |
| if dev not in zfs_devices: | |
| zfs_devices[dev] = [] | |
| zfs_devices[dev].append(pool) | |
| from pprint import pprint | |
| for dev in devices: | |
| dev_path = f"/dev/disk/by-id/wwn-0x{dev['GUID']}" | |
| sz = subprocess.check_output(["lsblk", "--output", "SIZE", "-n", "-d", dev_path], text=True).strip() | |
| # lsblk -nlo TYPE,NAME --json | |
| parent = dev_to_disk(dev_path) | |
| pools = zfs_devices.get(parent, "") | |
| if pools: | |
| pools = ",".join(sorted(pools)) | |
| print(f"{dev['Enclosure #']}:{dev['Slot #']}", dev['Model Number'], f"({dev['Serial No']})", sz, parent, pools) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment