]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph-volume: allow listing devices by OSD ID
authorRishabh Dave <ridave@redhat.com>
Thu, 19 Nov 2020 13:06:38 +0000 (18:36 +0530)
committerGuillaume Abrioux <gabrioux@redhat.com>
Thu, 7 Jul 2022 20:21:26 +0000 (22:21 +0200)
Adds the ability to list devices by OSD IDs, i.e. "ceph-volume lvm list
3" would list all devices under OSD ID 3 (which can be up to 2 and 3
devices under filestore and bluestore OSDs respectively).

Fixes: https://tracker.ceph.com/issues/41294
Signed-off-by: Rishabh Dave <ridave@redhat.com>
(cherry picked from commit 0792a396ce61b356ad004ac3dbd96fabed739eac)

src/ceph-volume/ceph_volume/devices/lvm/listing.py
src/ceph-volume/ceph_volume/tests/devices/lvm/test_listing.py

index 1ae8489f6fcb69d5008d6ca7e47173bfe81ead15..de19790511bfe9220a7b36425e83a0f7c518dad4 100644 (file)
@@ -140,12 +140,7 @@ class List(object):
         """
         return self.create_report(api.get_lvs())
 
-    def single_report(self, device):
-        """
-        Generate a report for a single device. This can be either a logical
-        volume in the form of vg/lv or a device with an absolute path like
-        /dev/sda1 or /dev/sda. Returns '{}' to denote failure.
-        """
+    def get_lvs_from_path(self, device):
         lvs = []
         if os.path.isabs(device):
             # we have a block device
@@ -159,13 +154,30 @@ class List(object):
             lvs = api.get_lvs(filters={'lv_name': lv_name,
                                        'vg_name': vg_name})
 
-        report = self.create_report(lvs)
+        return lvs
+
+    def single_report(self, arg):
+        """
+        Generate a report for a single device. This can be either a logical
+        volume in the form of vg/lv, a device with an absolute path like
+        /dev/sda1 or /dev/sda, or a list of devices under same OSD ID.
+
+        Return value '{}' denotes failure.
+        """
+        if isinstance(arg, int) or arg.isdigit():
+            lv = api.get_lvs_from_osd_id(arg)
+        elif arg[0] == '/':
+            lv = self.get_lvs_from_path(arg)
+        else:
+            lv = [api.get_single_lv(filters={'lv_name': arg.split('/')[1]})]
+
+        report = self.create_report(lv)
 
         if not report:
             # check if device is a non-lvm journals or wal/db
             for dev_type in ['journal', 'wal', 'db']:
                 lvs = api.get_lvs(tags={
-                    'ceph.{}_device'.format(dev_type): device})
+                    'ceph.{}_device'.format(dev_type): arg})
                 if lvs:
                     # just taking the first lv here should work
                     lv = lvs[0]
@@ -190,6 +202,10 @@ class List(object):
 
             ceph-volume lvm list
 
+        List devices under same OSD ID::
+
+            ceph-volume lvm list <OSD-ID>
+
         List a particular device, reporting all metadata about it::
 
             ceph-volume lvm list /dev/sda1
index c72b6155cc986bce17a34adfe4698b20bc69cd1d..7e4d963c8b450f1a813a03bcd80544b747e1230d 100644 (file)
@@ -242,6 +242,93 @@ class TestSingleReport(object):
         assert result['0'][0]['path'] == '/dev/VolGroup/lv'
         assert result['0'][0]['devices'] == ['/dev/sda1', '/dev/sdb1']
 
+    def test_report_by_osd_id_for_just_block_dev(self, monkeypatch):
+        tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=block'
+        lvs = [ api.Volume(lv_name='lv1', lv_tags=tags, lv_path='/dev/vg/lv1',
+                           lv_uuid='aaaa', vg_name='vg')
+              ]
+        monkeypatch.setattr(lvm.listing.api, 'get_lvs', lambda **kwargs: lvs)
+
+        listing = lvm.listing.List([])
+        result = listing.single_report(0)
+        assert result['0'][0]['name'] == 'lv1'
+        assert result['0'][0]['lv_tags'] == tags
+        assert result['0'][0]['lv_path'] == '/dev/vg/lv1'
+        assert result['0'][0]['vg_name'] == 'vg'
+
+    def test_report_by_osd_id_for_just_data_dev(self, monkeypatch):
+        tags = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data'
+        lvs = [ api.Volume(lv_name='lv1', lv_tags=tags, lv_path='/dev/vg/lv1',
+                           lv_uuid='bbbb', vg_name='vg'),
+                ]
+        monkeypatch.setattr(lvm.listing.api, 'get_lvs', lambda **kwargs: lvs)
+
+        listing = lvm.listing.List([])
+        result = listing.single_report(0)
+        assert result['0'][0]['name'] == 'lv1'
+        assert result['0'][0]['lv_tags'] == tags
+        assert result['0'][0]['lv_path'] == '/dev/vg/lv1'
+        assert result['0'][0]['vg_name'] == 'vg'
+
+    def test_report_by_osd_id_for_just_block_wal_and_db_dev(self, monkeypatch):
+        tags1 = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=block'
+        tags2 = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=wal'
+        tags3 = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=db'
+        lvs = [ api.Volume(lv_name='lv1', lv_tags=tags1, lv_path='/dev/vg/lv1',
+                           lv_uuid='aaaa', vg_name='vg'),
+                api.Volume(lv_name='lv2', lv_tags=tags2, lv_path='/dev/vg/lv2',
+                           lv_uuid='bbbb', vg_name='vg'),
+                api.Volume(lv_name='lv3', lv_tags=tags3, lv_path='/dev/vg/lv3',
+                           lv_uuid='cccc', vg_name='vg'),
+              ]
+        monkeypatch.setattr(lvm.listing.api, 'get_lvs', lambda **kwargs: lvs)
+
+        listing = lvm.listing.List([])
+        result = listing.single_report(0)
+        assert result['0'][0]['name'] == 'lv1'
+        assert result['0'][0]['lv_tags'] == tags1
+        assert result['0'][0]['lv_path'] == '/dev/vg/lv1'
+        assert result['0'][0]['vg_name'] == 'vg'
+        assert result['0'][1]['name'] == 'lv2'
+        assert result['0'][1]['lv_tags'] == tags2
+        assert result['0'][1]['lv_path'] == '/dev/vg/lv2'
+        assert result['0'][1]['vg_name'] == 'vg'
+        assert result['0'][2]['name'] == 'lv3'
+        assert result['0'][2]['lv_tags'] == tags3
+        assert result['0'][2]['lv_path'] == '/dev/vg/lv3'
+        assert result['0'][2]['vg_name'] == 'vg'
+
+
+    def test_report_by_osd_id_for_data_and_journal_dev(self, monkeypatch):
+        tags1 = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=data'
+        tags2 = 'ceph.osd_id=0,ceph.journal_uuid=x,ceph.type=journal'
+        lvs = [ api.Volume(lv_name='lv1', lv_tags=tags1, lv_path='/dev/vg/lv1',
+                    lv_uuid='aaaa', vg_name='vg'),
+                api.Volume(lv_name='lv2', lv_tags=tags2, lv_path='/dev/vg/lv2',
+                    lv_uuid='bbbb', vg_name='vg'),
+              ]
+        monkeypatch.setattr(lvm.listing.api, 'get_lvs', lambda **kwargs: lvs)
+
+        listing = lvm.listing.List([])
+        result = listing.single_report(0)
+        assert result['0'][0]['name'] == 'lv1'
+        assert result['0'][0]['lv_tags'] == tags1
+        assert result['0'][0]['lv_path'] == '/dev/vg/lv1'
+        assert result['0'][0]['vg_name'] == 'vg'
+        assert result['0'][1]['name'] == 'lv2'
+        assert result['0'][1]['lv_tags'] == tags2
+        assert result['0'][1]['lv_path'] == '/dev/vg/lv2'
+        assert result['0'][1]['vg_name'] == 'vg'
+
+    def test_report_by_nonexistent_osd_id(self, monkeypatch):
+        lv = api.Volume(lv_name='lv', lv_tags={}, lv_path='/dev/VolGroup/lv',
+                        vg_name='VolGroup')
+        monkeypatch.setattr(lvm.listing.api, 'get_lvs', lambda **kwargs:
+                            [lv])
+
+        result = lvm.listing.List([]).single_report('1')
+        assert result == {}
+
     def test_report_a_ceph_lv_with_no_matching_devices(self, monkeypatch):
         tags = 'ceph.osd_id=0,ceph.type=data'
         lv = api.Volume(lv_name='lv', vg_name='VolGroup', lv_uuid='aaaa',