from glob import glob
from os.path import basename, dirname
def physical_drives():
drive_glob = '/sys/block/*/device'
return [basename(dirname(pd)) for pd in glob(drive_glob)]
def partitions(disk):
if disk.startswith('.') or '/' in disk:
raise ValueError('Invalid disk name {0}'.format(disk))
part_globpartition_glob = '/sys/block/{0}/*/start'.format(disk)
return [basename(dirname(p)) for p in glob(part_globpartition_glob)]
from glob import glob
from os.path import basename, dirname
def physical_drives():
drive_glob = '/sys/block/*/device'
return [basename(dirname(p)) for p in glob(drive_glob)]
def partitions(disk):
if disk.startswith('.') or '/' in disk:
raise ValueError('Invalid disk name {0}'.format(disk))
part_glob = '/sys/block/{0}/*/start'.format(disk)
return [basename(dirname(p)) for p in glob(part_glob)]
from glob import glob
from os.path import basename, dirname
def physical_drives():
drive_glob = '/sys/block/*/device'
return [basename(dirname(d)) for d in glob(drive_glob)]
def partitions(disk):
if disk.startswith('.') or '/' in disk:
raise ValueError('Invalid disk name {0}'.format(disk))
partition_glob = '/sys/block/{0}/*/start'.format(disk)
return [basename(dirname(p)) for p in glob(partition_glob)]
lsblk
The -s
option to lsblk
was introduced to util-linux rather recently, in release 2.22. You may experience compatibility issues on slightly older GNU/Linux installations.
But I don't see why you would want the -s
option at all — it just gives you an inverted device tree. For example, on my machine:
$ lsblk -o name -n -s -l sda1 sda sda2 sda sr0 vg-root sda3 sda vg-var sda3 sda vg-data sda3 sda
In the output, sda
appears multiple times. To understand the output, you need to drop the -l
flag so that the list appears in tree form:
$ lsblk -o name -n -s sda1 └─sda sda2 └─sda sr0 vg-root └─sda3 └─sda vg-var └─sda3 └─sda vg-data └─sda3 └─sda
Now, it's more apparent that the -s
option isn't helpful. If you drop it, then the output makes more sense:
$ lsblk -o name -n sda ├─sda1 ├─sda2 └─sda3 ├─vg-root ├─vg-var └─vg-data sr0 $ lsblk -o name -n -l sda sda1 sda2 sda3 vg-root vg-var vg-data sr0
To list the devices on sda
, it would be better to run lsblk -o name -n -l /dev/sda
— that would immediately drop sr0
from consideration, for example. Note that LVM volumes (such as vg-root
above) would still appear in the output. I don't think that doing a substring search (if x != disk and disk in x
in your code) is a reliable filter. It could be fooled if there are more than 26 physical disks: the 27th disk would be named sdaa
. It might also be fooled by exceptionally tricky naming of LVM volumes.
Subprocess execution
Whenever practical, I recommend avoiding the shell when executing subprocesses. The shell introduces a set of potential security vulnerabilities — for example, shenanigans with the PATH
environment variable. Best practice would be to run the command with a specific executable and pre-parsed command-line options:
run('/bin/lsblk -o name -n -s -l'.split(), stdout=PIPE)
Alternative solution
I actually wouldn't bother with parsing the output of lsblk
at all. After all, lsblk
is just a way to report the contents of the sysfs filesystem. You would be better off inspecting /sys
directly.
from glob import glob
from os.path import basename, dirname
def physical_drives():
drive_glob = '/sys/block/*/device'
return [basename(dirname(p)) for p in glob(drive_glob)]
def partitions(disk):
if disk.startswith('.') or '/' in disk:
raise ValueError('Invalid disk name {0}'.format(disk))
part_glob = '/sys/block/{0}/*/start'.format(disk)
return [basename(dirname(p)) for p in glob(part_glob)]