Last active
May 30, 2021 07:05
-
-
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`)
This file contains 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/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() |
This file contains 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
{ | |
"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" | |
} | |
} |
This file contains 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
{ | |
"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