Skip to content

Instantly share code, notes, and snippets.

@balamurugana
Last active May 30, 2021 07:05
Show Gist options
  • Save balamurugana/11e36601034adc4d62386caad0809a3b to your computer and use it in GitHub Desktop.
Save balamurugana/11e36601034adc4d62386caad0809a3b to your computer and use it in GitHub Desktop.
Find drives and identify uniquely upon every run (execute by `sudo python find-drives.py`)
#!/usr/bin/python
import json
import os
import subprocess
def _read_file(filename):
try:
with open(filename) as file:
return file.read().strip()
except FileNotFoundError:
return ""
def _lsblk():
proc = subprocess.run(
[
"lsblk", "--all", "--bytes", "--json",
"--output=KNAME,FSTYPE,UUID,PTUUID,PTTYPE,PARTUUID,TYPE",
],
capture_output=True,
check=True,
text=True,
)
return json.loads(proc.stdout) if proc.stdout else {}
def _get_drives():
names = os.listdir("/sys/class/block")
drives = {}
for name in names:
model = _read_file("/sys/class/block/{0}/device/model".format(name))
serial = _read_file("/sys/class/block/{0}/device/serial".format(name))
vendor = _read_file("/sys/class/block/{0}/device/vendor".format(name))
size = _read_file("/sys/class/block/{0}/size".format(name))
nguid = _read_file("/sys/class/block/{0}/nguid".format(name))
uuid = _read_file("/sys/class/block/{0}/uuid".format(name))
wwid = _read_file("/sys/class/block/{0}/wwid".format(name))
mduuid = _read_file("/sys/class/block/{0}/md/uuid".format(name))
dmuuid = _read_file("/sys/class/block/{0}/dm/uuid".format(name))
drive = {"name": name}
drive.update({"model": model} if model else {})
drive.update({"serial": serial} if serial else {})
drive.update({"vendor": vendor} if vendor else {})
drive.update({"size": size} if size else {})
drive.update({"nguid": nguid} if nguid else {})
drive.update({"uuid": uuid} if uuid else {})
drive.update({"wwid": wwid} if wwid else {})
drive.update({"mduuid": mduuid} if mduuid else {})
drive.update({"dmuuid": dmuuid} if dmuuid else {})
drives[name] = drive
return drives
def get_drives():
drives = _get_drives()
output = _lsblk()
for device in output.get("blockdevices", {}):
name = device["kname"]
drives[name].update(
{"fsuuid": device["uuid"]} if device["uuid"] else {},
)
drives[name].update(
{"fstype": device["fstype"]} if device["fstype"] else {},
)
if device["type"] == "part":
drives[name].update(
{"partuuid": device["partuuid"]} if device["partuuid"] else {},
)
else:
drives[name].update(
{"ptuuid": device["ptuuid"]} if device["ptuuid"] else {},
)
drives[name].update(
{"pttype": device["pttype"]} if device["pttype"] else {},
)
return drives
def _read_config():
try:
with open("drives.json") as file:
return json.load(file)
except FileNotFoundError:
return {}
def _write_config(drives):
with open("drives.json", "w") as file:
json.dump(drives, file)
def _compute_id(drive):
drive_id = (
drive.get("wwid") or drive.get("nguid") or drive.get("uuid") or
drive.get("mduuid") or drive.get("dmuuid")
)
if drive_id:
return drive_id
if drive.get("serial"):
return (
drive["serial"] +
drive.get("model", "") +
drive.get("vendor", "") +
drive["size"]
)
return (
drive.get("model", "") +
drive.get("vendor", "") +
drive["size"] +
drive.get("ptuuid", "") +
drive.get("pttype", "") +
drive.get("fsuuid", "") +
drive.get("fstype", "") +
drive.get("partuuid", "")
)
def _get_drive_id_dict(drives):
drive_id_dict = {}
for name, drive in drives.items():
drive_id = _compute_id(drive)
names = drive_id_dict.get(drive_id, [])
names.append(name)
drive_id_dict[drive_id] = names
return drive_id_dict
def main():
drives = _read_config()
probed_drives = get_drives()
_write_config(probed_drives)
if drives == probed_drives:
return
drive_id_dict = _get_drive_id_dict(drives)
probed_drive_id_dict = _get_drive_id_dict(probed_drives)
print(drive_id_dict, probed_drive_id_dict)
for drive_id, names in probed_drive_id_dict.items():
if not drive_id_dict.get(drive_id):
print("[NEW]", names)
elif names != drive_id_dict[drive_id]:
print("[RENAMED]", drive_id_dict[drive_id], "->", names)
for drive_id, names in drive_id_dict.items():
if not probed_drive_id_dict.get(drive_id):
print("[REMOVED]", names)
main()
{
"loop1": {
"name": "loop1",
"size": "2097152",
"fsuuid": "X1GyIn-sMNT-22B3-1iXo-7M5u-zSJP-MYDhsF",
"fstype": "LVM2_member"
},
"dm-1": {
"name": "dm-1",
"size": "1048576",
"dmuuid": "LVM-ExlCQpOh5VGw0wPLe9XDjf0OXaWchRSQpztjTcvOpcLx3bmPEXc7oXaVyPXoNj2Y"
},
"nvme0n1": {
"name": "nvme0n1",
"model": "Micron 2300 NVMe 512GB",
"serial": "20402AC616B5",
"size": "1000215216",
"nguid": "00000000-0000-0001-00a0-75202ac616b5",
"uuid": "00000000-0000-0001-00a0-75202ac616b5",
"wwid": "eui.000000000000000100a075202ac616b5",
"ptuuid": "6ce102c7-cfc2-4b1c-b658-02ba8cd9f58f",
"pttype": "gpt"
},
"nvme0n1p3": {
"name": "nvme0n1p3",
"size": "104857600",
"fsuuid": "c368448a-f045-4aa2-a424-c55bc952eb74",
"fstype": "ext4",
"partuuid": "89fc4f86-1519-47c8-a9f1-11ed504c8f18"
},
"md0": {
"name": "md0",
"size": "4186112",
"mduuid": "236ec452-7b04-5c0a-5fd7-337d335f44eb"
},
"nvme0n1p1": {
"name": "nvme0n1p1",
"size": "1228800",
"fsuuid": "D5C0-A5C2",
"fstype": "vfat",
"partuuid": "0d167e49-2c8d-4c6c-ad82-b5e66b6a9eda"
},
"loop2": {
"name": "loop2",
"size": "2097152",
"fsuuid": "236ec452-7b04-5c0a-5fd7-337d335f44eb",
"fstype": "linux_raid_member"
},
"loop0": {
"name": "loop0",
"size": "2097152",
"fsuuid": "hGm8UY-JIr9-rdge-dk85-2nDM-SWS2-iZ7oC2",
"fstype": "LVM2_member"
},
"dm-0": {
"name": "dm-0",
"size": "2097152",
"dmuuid": "LVM-ExlCQpOh5VGw0wPLe9XDjf0OXaWchRSQ7HXQQj5ZbL4c5dEdLFNOatT9YozRg19g"
},
"nvme0n1p4": {
"name": "nvme0n1p4",
"size": "892028928",
"fsuuid": "886e06e8-1639-41f4-9b78-da266d9fe8b2",
"fstype": "ext4",
"partuuid": "8a7d885f-88ba-4734-bbc7-90881480a5a6"
},
"zram0": {
"name": "zram0",
"size": "8388608"
},
"nvme0n1p2": {
"name": "nvme0n1p2",
"size": "2097152",
"fsuuid": "9b7c849b-387e-43f8-ad5a-b7d68c5c062f",
"fstype": "ext4",
"partuuid": "a183b96b-072c-4236-ae9a-d8adce39859d"
},
"loop3": {
"name": "loop3",
"size": "2097152",
"fsuuid": "236ec452-7b04-5c0a-5fd7-337d335f44eb",
"fstype": "linux_raid_member"
}
}
{
"sdc2": {
"name": "sdc2",
"size": "20372",
"fsuuid": "CD28-2F9A",
"fstype": "vfat",
"partuuid": "6b5ab614-02"
},
"sda2": {
"name": "sda2",
"size": "2",
"partuuid": "8961d622-02"
},
"sdb": {
"name": "sdb",
"model": "Ultra",
"vendor": "SanDisk",
"size": "121307136",
"pttype": "dos"
},
"sda5": {
"name": "sda5",
"size": "400091136",
"fsuuid": "69b6e998-581c-4850-94fd-9b827f30706f",
"fstype": "ext4",
"partuuid": "8961d622-05"
},
"sdc3": {
"name": "sdc3",
"size": "42848",
"fsuuid": "92c9f606-d33d-3955-aca0-ba75d9117ecb",
"fstype": "hfsplus",
"partuuid": "6b5ab614-03"
},
"sdc1": {
"name": "sdc1",
"size": "3920640",
"fsuuid": "2021-04-23-11-17-40-00",
"fstype": "iso9660",
"partuuid": "6b5ab614-01"
},
"sdb1": {
"name": "sdb1",
"size": "121307104",
"fsuuid": "F56C-281E",
"fstype": "vfat"
},
"sdc": {
"name": "sdc",
"model": "DataTraveler G2",
"vendor": "Kingston",
"size": "7827392",
"fsuuid": "2021-04-23-11-17-40-00",
"fstype": "iso9660",
"ptuuid": "6b5ab614",
"pttype": "dos"
},
"sda1": {
"name": "sda1",
"size": "100022272",
"fsuuid": "22990c89-cd91-4d71-83b2-676dbd3d30f4",
"fstype": "ext4",
"partuuid": "8961d622-01"
},
"sda": {
"name": "sda",
"model": "SAMSUNG MZNTY256",
"vendor": "ATA",
"size": "500118192",
"ptuuid": "8961d622",
"pttype": "dos"
},
"zram0": {
"name": "zram0",
"size": "14839808"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment