Skip to content

Commit

Permalink
ceph-volume: fixes fallback to stat in is_device and is_partition
Browse files Browse the repository at this point in the history
os.stat (or lstat) cannot distinguish a block device from
a partition.

Fixes: https://tracker.ceph.com/issues/58812

Signed-off-by: Teoman ONAY <tonay@ibm.com>
  • Loading branch information
asm0deuz committed Nov 20, 2023
1 parent 39fea8f commit 52ca4a6
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 24 deletions.
8 changes: 0 additions & 8 deletions src/ceph-volume/ceph_volume/tests/util/test_device.py
Expand Up @@ -152,14 +152,6 @@ def test_disk_is_device(self, fake_call, device_info):
disk = device.Device("/dev/sda")
assert disk.is_device is True

@patch("ceph_volume.util.disk.has_bluestore_label", lambda x: False)
def test_is_partition(self, fake_call, device_info):
data = {"/dev/sda1": {"foo": "bar"}}
lsblk = {"TYPE": "part", "NAME": "sda1", "PKNAME": "sda"}
device_info(devices=data, lsblk=lsblk)
disk = device.Device("/dev/sda1")
assert disk.is_partition

@patch("ceph_volume.util.disk.has_bluestore_label", lambda x: False)
def test_mpath_device_is_device(self, fake_call, device_info):
data = {"/dev/foo": {"foo": "bar"}}
Expand Down
5 changes: 5 additions & 0 deletions src/ceph-volume/ceph_volume/tests/util/test_disk.py
Expand Up @@ -33,6 +33,11 @@ def test_is_device_type_mpath(self):
def test_is_device_type_part(self):
assert not disk.is_device('/dev/foo1')

@patch('ceph_volume.util.disk.os.path.exists', MagicMock(return_value=True))
@patch('ceph_volume.util.disk.get_partitions', MagicMock(return_value={"sda1": "sda"}))
def test_is_partition(self):
assert disk.is_partition('sda1')


class TestLsblkParser(object):

Expand Down
20 changes: 4 additions & 16 deletions src/ceph-volume/ceph_volume/util/disk.py
Expand Up @@ -364,30 +364,18 @@ def is_device(dev):
return TYPE in ['disk', 'mpath']

# fallback to stat
return _stat_is_device(os.lstat(dev).st_mode)
return _stat_is_device(os.lstat(dev).st_mode) and not is_partition(dev)


def is_partition(dev):
def is_partition(dev: str) -> bool:
"""
Boolean to determine if a given device is a partition, like /dev/sda1
"""
if not os.path.exists(dev):
return False
# use lsblk first, fall back to using stat
TYPE = lsblk(dev).get('TYPE')
if TYPE:
return TYPE == 'part'

# fallback to stat
stat_obj = os.stat(dev)
if _stat_is_device(stat_obj.st_mode):
return False

major = os.major(stat_obj.st_rdev)
minor = os.minor(stat_obj.st_rdev)
if os.path.exists('/sys/dev/block/%d:%d/partition' % (major, minor)):
return True
return False
partitions = get_partitions()
return dev.split("/")[-1] in partitions


def is_ceph_rbd(dev):
Expand Down

0 comments on commit 52ca4a6

Please sign in to comment.