Skip to content

Instantly share code, notes, and snippets.

@wjdp
Created January 14, 2025 02:46
Show Gist options
  • Save wjdp/e232eaf882cb84da32291a2a624e92a6 to your computer and use it in GitHub Desktop.
Save wjdp/e232eaf882cb84da32291a2a624e92a6 to your computer and use it in GitHub Desktop.
Locate and identify disk using any symlink type
#!/usr/bin/env python3
import sys
import os
from typing import NamedTuple
import subprocess
def printc(text, colour):
"""Print text in color."""
colours = {
"red": "\033[91m",
"green": "\033[92m",
"yellow": "\033[93m",
"blue": "\033[94m",
"purple": "\033[95m",
"cyan": "\033[96m",
"white": "\033[97m",
"gray": "\033[90m",
"reset": "\033[0m",
}
print(colours[colour] + text + colours["reset"])
DISK_PATHS = [
"/dev/",
"/dev/disk/by-id/",
"/dev/disk/by-vdev/",
"/dev/disk/by-path/",
"/dev/disk/by-uuid/",
"/dev/disk/by-label/",
]
PREFERED_PATH = "/dev/disk/by-vdev/"
def find_disk_path(disk_identifier):
for path in DISK_PATHS:
if os.path.exists(path + disk_identifier):
return path + disk_identifier
def normalize_path(path):
"""Resolve the symbolic link of a path."""
return os.path.realpath(path)
def find_other_links(normal_path):
"""Find other links to the same disk."""
for path in DISK_PATHS:
# loop through all the paths in the directory checking if they are links to the same disk
for file in os.listdir(path):
if os.path.islink(path + file):
if os.path.realpath(path + file) == normal_path:
yield path + file
class DiskInfo(NamedTuple):
name: str
model: str
capacity: str
serial: str
state: str
wwn: str
def get_disk_info(disk_path):
"""Get disk information."""
get_info = lambda x: subprocess.check_output(x, shell=True).decode().strip()
return DiskInfo(
name=get_info(f"lsblk -ndo NAME {disk_path}"),
model=get_info(f"lsblk -ndo MODEL {disk_path}"),
capacity=get_info(f"lsblk -ndo SIZE {disk_path}"),
serial=get_info(f"lsblk -ndo SERIAL {disk_path}"),
state=get_info(f"lsblk -ndo STATE {disk_path}"),
wwn=get_info(f"lsblk -ndo WWN {disk_path}"),
)
def choose_preferred_path(paths):
for path in paths:
if path.startswith(PREFERED_PATH):
return path
arg = sys.argv[1]
# only the file part of the path is needed
if "/" in arg:
arg = os.path.basename(arg)
disk_path = find_disk_path(arg)
if not disk_path:
printc("Disk not found", "red")
sys.exit(1)
normal_path = normalize_path(disk_path)
other_links = list(find_other_links(normal_path))
preferred_path = choose_preferred_path(other_links)
disk_info = get_disk_info(disk_path)
if preferred_path:
printc(f"--- DISK {preferred_path.removeprefix(PREFERED_PATH)} ---", "green")
else:
printc(f"DISK {disk_path}", "yellow")
print(f"Device: {normal_path}")
print(f"Name: {disk_info.name}")
print(f"Model: {disk_info.model}")
print(f"Capacity: {disk_info.capacity}")
print(f"Serial: {disk_info.serial}")
print(f"State: {disk_info.state}")
print(f"WWN: {disk_info.wwn}")
for link in other_links:
printc(f"Alias: {link}", colour="gray")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment