diff --git a/src/ceph-volume/ceph_volume/tests/conftest.py b/src/ceph-volume/ceph_volume/tests/conftest.py index e9dbd123eeda4..fad7df44e305d 100644 --- a/src/ceph-volume/ceph_volume/tests/conftest.py +++ b/src/ceph-volume/ceph_volume/tests/conftest.py @@ -1,6 +1,7 @@ import os import pytest from ceph_volume.util import disk +from ceph_volume.util.constants import ceph_disk_guids from ceph_volume.api import lvm as lvm_api from ceph_volume import conf, configuration @@ -192,6 +193,67 @@ def generate_file(name='file', contents='', directory=None): return generate_file +@pytest.fixture +def disable_kernel_queries(monkeypatch): + ''' + This speeds up calls to Device and Disk + ''' + monkeypatch.setattr("ceph_volume.util.device.disk.get_devices", lambda: {}) + monkeypatch.setattr("ceph_volume.util.disk.udevadm_property", lambda *a, **kw: {}) + + +@pytest.fixture +def disable_lvm_queries(monkeypatch): + ''' + This speeds up calls to Device and Disk + ''' + monkeypatch.setattr("ceph_volume.util.device.lvm.get_lv_from_argument", lambda path: None) + monkeypatch.setattr("ceph_volume.util.device.lvm.get_lv", lambda vg_name, lv_uuid: None) + + +@pytest.fixture(params=[ + '', 'ceph data', 'ceph journal', 'ceph block', + 'ceph block.wal', 'ceph block.db', 'ceph lockbox']) +def ceph_partlabel(request): + return request.param + + +@pytest.fixture(params=list(ceph_disk_guids.keys())) +def ceph_parttype(request): + return request.param + + +@pytest.fixture +def lsblk_ceph_disk_member(monkeypatch, request, ceph_partlabel, ceph_parttype): + monkeypatch.setattr("ceph_volume.util.device.disk.lsblk", + lambda path: {'PARTLABEL': ceph_partlabel}) + # setting blkid here too in order to be able to fall back to PARTTYPE based + # membership + monkeypatch.setattr("ceph_volume.util.device.disk.blkid", + lambda path: {'PARTLABEL': '', + 'PARTTYPE': ceph_parttype}) + + +@pytest.fixture +def blkid_ceph_disk_member(monkeypatch, request, ceph_partlabel, ceph_parttype): + monkeypatch.setattr("ceph_volume.util.device.disk.blkid", + lambda path: {'PARTLABEL': ceph_partlabel, + 'PARTTYPE': ceph_parttype}) + + +@pytest.fixture(params=[ + ('gluster partition', 'gluster partition'), + # falls back to blkid + ('', 'gluster partition'), + ('gluster partition', ''), +]) +def device_info_not_ceph_disk_member(monkeypatch, request): + monkeypatch.setattr("ceph_volume.util.device.disk.lsblk", + lambda path: {'PARTLABEL': request.param[0]}) + monkeypatch.setattr("ceph_volume.util.device.disk.blkid", + lambda path: {'PARTLABEL': request.param[1]}) + + @pytest.fixture def device_info(monkeypatch): def apply(devices=None, lsblk=None, lv=None, blkid=None, udevadm=None): diff --git a/src/ceph-volume/ceph_volume/tests/util/test_device.py b/src/ceph-volume/ceph_volume/tests/util/test_device.py index dca379cbbefec..3a098d7ed2d41 100644 --- a/src/ceph-volume/ceph_volume/tests/util/test_device.py +++ b/src/ceph-volume/ceph_volume/tests/util/test_device.py @@ -136,39 +136,46 @@ def test_is_not_mapper_device(self, device_info): disk = device.Device("/dev/sda") assert not disk.is_mapper - def test_is_ceph_disk_member_lsblk(self, device_info): - lsblk = {"PARTLABEL": "ceph data"} - device_info(lsblk=lsblk) + @pytest.mark.usefixtures("lsblk_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_is_ceph_disk_lsblk(self, monkeypatch): disk = device.Device("/dev/sda") assert disk.is_ceph_disk_member - def test_is_ceph_disk_member_not_available(self, device_info): - lsblk = {"PARTLABEL": "ceph data"} - device_info(lsblk=lsblk) + @pytest.mark.usefixtures("blkid_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_is_ceph_disk_blkid(self, monkeypatch): + monkeypatch.setattr("ceph_volume.util.device.disk.lsblk", + lambda path: {'PARTLABEL': ""}) disk = device.Device("/dev/sda") assert disk.is_ceph_disk_member - assert not disk.available - assert "Used by ceph-disk" in disk.rejected_reasons - def test_is_not_ceph_disk_member_lsblk(self, device_info): - lsblk = {"PARTLABEL": "gluster partition"} - device_info(lsblk=lsblk) + @pytest.mark.usefixtures("lsblk_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_is_ceph_disk_member_not_available_lsblk(self, monkeypatch): disk = device.Device("/dev/sda") - assert disk.is_ceph_disk_member is False + assert disk.is_ceph_disk_member + assert not disk.available + assert "Used by ceph-disk" in disk.rejected_reasons - def test_is_ceph_disk_member_blkid(self, device_info): - # falls back to blkid - lsblk = {"PARTLABEL": ""} - blkid = {"PARTLABEL": "ceph data"} - device_info(lsblk=lsblk, blkid=blkid) + @pytest.mark.usefixtures("blkid_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_is_ceph_disk_member_not_available_blkid(self, monkeypatch): + monkeypatch.setattr("ceph_volume.util.device.disk.lsblk", + lambda path: {'PARTLABEL': ""}) disk = device.Device("/dev/sda") assert disk.is_ceph_disk_member + assert not disk.available + assert "Used by ceph-disk" in disk.rejected_reasons - def test_is_not_ceph_disk_member_blkid(self, device_info): - # falls back to blkid - lsblk = {"PARTLABEL": ""} - blkid = {"PARTLABEL": "gluster partition"} - device_info(lsblk=lsblk, blkid=blkid) + @pytest.mark.usefixtures("device_info_not_ceph_disk_member", + "disable_lvm_queries", + "disable_kernel_queries") + def test_is_not_ceph_disk_member_lsblk(self): disk = device.Device("/dev/sda") assert disk.is_ceph_disk_member is False @@ -360,12 +367,6 @@ def test_invalid_alphabetical_ordering(self, device_info): assert sdd > sdb -ceph_partlabels = [ - 'ceph data', 'ceph journal', 'ceph block', - 'ceph block.wal', 'ceph block.db', 'ceph lockbox' -] - - class TestCephDiskDevice(object): def test_partlabel_lsblk(self, device_info): @@ -383,11 +384,12 @@ def test_partlabel_blkid(self, device_info): assert disk.partlabel == 'ceph data' - @pytest.mark.parametrize("label", ceph_partlabels) - def test_is_member_blkid(self, device_info, label): - lsblk = {"PARTLABEL": ""} - blkid = {"PARTLABEL": label} - device_info(lsblk=lsblk, blkid=blkid) + @pytest.mark.usefixtures("blkid_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_is_member_blkid(self, monkeypatch): + monkeypatch.setattr("ceph_volume.util.device.disk.lsblk", + lambda path: {'PARTLABEL': ""}) disk = device.CephDiskDevice(device.Device("/dev/sda")) assert disk.is_member is True @@ -416,10 +418,10 @@ def test_accept_non_readonly_device(self, device_info): disk = device.Device("/dev/sda") assert disk.available - @pytest.mark.parametrize("label", ceph_partlabels) - def test_is_member_lsblk(self, device_info, label): - lsblk = {"PARTLABEL": label} - device_info(lsblk=lsblk) + @pytest.mark.usefixtures("lsblk_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_is_member_lsblk(self): disk = device.CephDiskDevice(device.Device("/dev/sda")) assert disk.is_member is True @@ -431,22 +433,23 @@ def test_unknown_type(self, device_info): assert disk.type == 'unknown' - @pytest.mark.parametrize("label", ceph_partlabels) - def test_type_blkid(self, device_info, label): - expected = label.split()[-1].split('.')[-1] - lsblk = {"PARTLABEL": ""} - blkid = {"PARTLABEL": label} - device_info(lsblk=lsblk, blkid=blkid) + ceph_types = ['data', 'wal', 'db', 'lockbox', 'journal', 'block'] + + @pytest.mark.usefixtures("blkid_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_type_blkid(self, monkeypatch, device_info, ceph_partlabel): + monkeypatch.setattr("ceph_volume.util.device.disk.lsblk", + lambda path: {'PARTLABEL': ''}) disk = device.CephDiskDevice(device.Device("/dev/sda")) - assert disk.type == expected + assert disk.type in self.ceph_types - @pytest.mark.parametrize("label", ceph_partlabels) - def test_type_lsblk(self, device_info, label): - expected = label.split()[-1].split('.')[-1] - lsblk = {"PARTLABEL": label} - blkid = {"PARTLABEL": ''} - device_info(lsblk=lsblk, blkid=blkid) + @pytest.mark.usefixtures("blkid_ceph_disk_member", + "lsblk_ceph_disk_member", + "disable_kernel_queries", + "disable_lvm_queries") + def test_type_lsblk(self, device_info, ceph_partlabel): disk = device.CephDiskDevice(device.Device("/dev/sda")) - assert disk.type == expected + assert disk.type in self.ceph_types diff --git a/src/ceph-volume/ceph_volume/util/constants.py b/src/ceph-volume/ceph_volume/util/constants.py index ac2832482e142..3ec819ec3a0b1 100644 --- a/src/ceph-volume/ceph_volume/util/constants.py +++ b/src/ceph-volume/ceph_volume/util/constants.py @@ -23,11 +23,24 @@ 'cafecafe-9b03-4f30-b4c6-35865ceff106': {'type': 'block', 'encrypted': True, 'encryption_type': 'luks'}, '166418da-c469-4022-adf4-b30afd37f176': {'type': 'block.db', 'encrypted': True, 'encryption_type': 'luks'}, '86a32090-3647-40b9-bbbd-38d8c573aa86': {'type': 'block.wal', 'encrypted': True, 'encryption_type': 'luks'}, - '4fbd7e29-9d25-41b8-afd0-35865ceff05d': {'type': 'osd', 'encrypted': True, 'encryption_type': 'luks'}, + '4fbd7e29-9d25-41b8-afd0-35865ceff05d': {'type': 'data', 'encrypted': True, 'encryption_type': 'luks'}, # plain '45b0969e-9b03-4f30-b4c6-5ec00ceff106': {'type': 'journal', 'encrypted': True, 'encryption_type': 'plain'}, 'cafecafe-9b03-4f30-b4c6-5ec00ceff106': {'type': 'block', 'encrypted': True, 'encryption_type': 'plain'}, '93b0052d-02d9-4d8a-a43b-33a3ee4dfbc3': {'type': 'block.db', 'encrypted': True, 'encryption_type': 'plain'}, '306e8683-4fe2-4330-b7c0-00a917c16966': {'type': 'block.wal', 'encrypted': True, 'encryption_type': 'plain'}, - '4fbd7e29-9d25-41b8-afd0-5ec00ceff05d': {'type': 'osd', 'encrypted': True, 'encryption_type': 'plain'}, + '4fbd7e29-9d25-41b8-afd0-5ec00ceff05d': {'type': 'data', 'encrypted': True, 'encryption_type': 'plain'}, + # regular guids that differ from plain + 'fb3aabf9-d25f-47cc-bf5e-721d1816496b': {'type': 'lockbox', 'encrypted': False, 'encryption_type': None}, + '30cd0809-c2b2-499c-8879-2d6b78529876': {'type': 'block.db', 'encrypted': False, 'encryption_type': None}, + '5ce17fce-4087-4169-b7ff-056cc58473f9': {'type': 'block.wal', 'encrypted': False, 'encryption_type': None}, + '4fbd7e29-9d25-41b8-afd0-062c0ceff05d': {'type': 'data', 'encrypted': False, 'encryption_type': None}, + 'cafecafe-9b03-4f30-b4c6-b4b80ceff106': {'type': 'block', 'encrypted': False, 'encryption_type': None}, + # multipath + '01b41e1b-002a-453c-9f17-88793989ff8f': {'type': 'block.wal', 'encrypted': False, 'encryption_type': None}, + 'ec6d6385-e346-45dc-be91-da2a7c8b3261': {'type': 'block.wal', 'encrypted': False, 'encryption_type': None}, + '45b0969e-8ae0-4982-bf9d-5a8d867af560': {'type': 'journal', 'encrypted': False, 'encryption_type': None}, + '4fbd7e29-8ae0-4982-bf9d-5a8d867af560': {'type': 'data', 'encrypted': False, 'encryption_type': None}, + '7f4a666a-16f3-47a2-8445-152ef4d03f6c': {'type': 'lockbox', 'encrypted': False, 'encryption_type': None}, + 'cafecafe-8ae0-4982-bf9d-5a8d867af560': {'type': 'block', 'encrypted': False, 'encryption_type': None}, } diff --git a/src/ceph-volume/ceph_volume/util/device.py b/src/ceph-volume/ceph_volume/util/device.py index f06cb41ee4e9a..ddec0e84804f5 100644 --- a/src/ceph-volume/ceph_volume/util/device.py +++ b/src/ceph-volume/ceph_volume/util/device.py @@ -5,6 +5,7 @@ from ceph_volume import sys_info from ceph_volume.api import lvm from ceph_volume.util import disk +from ceph_volume.util.constants import ceph_disk_guids report_template = """ {dev:<25} {size:<12} {rot!s:<7} {available!s:<9} {model}""" @@ -416,12 +417,24 @@ def partlabel(self): return lsblk_partlabel return self.device.blkid_api.get('PARTLABEL', '') + @property + def parttype(self): + """ + Seems like older version do not detect PARTTYPE correctly (assuming the + info in util/disk.py#lsblk is still valid). + SImply resolve to using blkid since lsblk will throw an error if asked + for an unknown columns + """ + return self.device.blkid_api.get('PARTTYPE', '') + @property def is_member(self): if self._is_ceph_disk_member is None: if 'ceph' in self.partlabel: self._is_ceph_disk_member = True return True + elif self.parttype in ceph_disk_guids.keys(): + return True return False return self._is_ceph_disk_member @@ -436,4 +449,5 @@ def type(self): for t in types: if t in self.partlabel: return t - return 'unknown' + label = ceph_disk_guids.get(self.parttype, {}) + return label.get('type', 'unknown').split('.')[-1] diff --git a/src/ceph-volume/ceph_volume/util/disk.py b/src/ceph-volume/ceph_volume/util/disk.py index 98239be3a445f..97799466434c5 100644 --- a/src/ceph-volume/ceph_volume/util/disk.py +++ b/src/ceph-volume/ceph_volume/util/disk.py @@ -51,6 +51,7 @@ def _blkid_parser(output): 'TYPE': 'TYPE', 'PART_ENTRY_NAME': 'PARTLABEL', 'PART_ENTRY_UUID': 'PARTUUID', + 'PART_ENTRY_TYPE': 'PARTTYPE', 'PTTYPE': 'PTTYPE', }