]> git.proxmox.com Git - ceph.git/blame - ceph/src/ceph-volume/ceph_volume/devices/raw/list.py
import 15.2.5
[ceph.git] / ceph / src / ceph-volume / ceph_volume / devices / raw / list.py
CommitLineData
92f5a8d4
TL
1from __future__ import print_function
2import argparse
3import json
4import logging
5from textwrap import dedent
6from ceph_volume import decorators, process
7
8
9logger = logging.getLogger(__name__)
10
11def direct_report(devices):
12 """
13 Other non-cli consumers of listing information will want to consume the
14 report without the need to parse arguments or other flags. This helper
15 bypasses the need to deal with the class interface which is meant for cli
16 handling.
17 """
18 _list = List([])
19 return _list.generate(devices)
20
21
22class List(object):
23
24 help = 'list BlueStore OSDs on raw devices'
25
26 def __init__(self, argv):
27 self.argv = argv
28
29 def generate(self, devs=None):
30 if not devs:
31 logger.debug('Listing block devices via lsblk...')
32 devs = []
f6b5b4d7
TL
33 # adding '--inverse' allows us to get the mapper devices list in that command output.
34 # not listing root devices containing partitions shouldn't have side effect since we are
35 # in `ceph-volume raw` context.
36 #
37 # example:
38 # running `lsblk --paths --nodeps --output=NAME --noheadings` doesn't allow to get the mapper list
39 # because the output is like following :
40 #
41 # $ lsblk --paths --nodeps --output=NAME --noheadings
42 # /dev/sda
43 # /dev/sdb
44 # /dev/sdc
45 # /dev/sdd
46 #
47 # the dmcrypt mappers are hidden because of the `--nodeps` given they are displayed as a dependency.
48 #
49 # $ lsblk --paths --output=NAME --noheadings
50 # /dev/sda
51 # |-/dev/mapper/ceph-3b52c90d-6548-407d-bde1-efd31809702f-sda-block-dmcrypt
52 # `-/dev/mapper/ceph-3b52c90d-6548-407d-bde1-efd31809702f-sda-db-dmcrypt
53 # /dev/sdb
54 # /dev/sdc
55 # /dev/sdd
56 #
57 # adding `--inverse` is a trick to get around this issue, the counterpart is that we can't list root devices if they contain
58 # at least one partition but this shouldn't be an issue in `ceph-volume raw` context given we only deal with raw devices.
92f5a8d4 59 out, err, ret = process.call([
f6b5b4d7 60 'lsblk', '--paths', '--nodeps', '--output=NAME', '--noheadings', '--inverse'
92f5a8d4
TL
61 ])
62 assert not ret
63 devs = out
64 result = {}
65 for dev in devs:
66 logger.debug('Examining %s' % dev)
67 # bluestore?
68 out, err, ret = process.call([
69 'ceph-bluestore-tool', 'show-label',
9f95a23c 70 '--dev', dev], verbose_on_failure=False)
92f5a8d4
TL
71 if ret:
72 logger.debug('No label on %s' % dev)
73 continue
74 oj = json.loads(''.join(out))
75 if dev not in oj:
76 continue
77 if oj[dev]['description'] != 'main':
78 # ignore non-main devices, for now
79 continue
80 whoami = oj[dev]['whoami']
81 result[whoami] = {
82 'type': 'bluestore',
83 'osd_id': int(whoami),
84 }
85 for f in ['osd_uuid', 'ceph_fsid']:
86 result[whoami][f] = oj[dev][f]
87 result[whoami]['device'] = dev
88 return result
89
90 @decorators.needs_root
91 def list(self, args):
92 report = self.generate(args.device)
93 if args.format == 'json':
94 print(json.dumps(report, indent=4, sort_keys=True))
95 else:
96 if not report:
97 raise SystemExit('No valid Ceph devices found')
98 raise RuntimeError('not implemented yet')
99
100 def main(self):
101 sub_command_help = dedent("""
102 List OSDs on raw devices with raw device labels (usually the first
103 block of the device).
104
105 Full listing of all identifiable (currently, BlueStore) OSDs
106 on raw devices:
107
108 ceph-volume raw list
109
110 List a particular device, reporting all metadata about it::
111
112 ceph-volume raw list /dev/sda1
113
114 """)
115 parser = argparse.ArgumentParser(
116 prog='ceph-volume raw list',
117 formatter_class=argparse.RawDescriptionHelpFormatter,
118 description=sub_command_help,
119 )
120
121 parser.add_argument(
122 'device',
123 metavar='DEVICE',
124 nargs='*',
125 help='Path to a device like /dev/sda1'
126 )
127
128 parser.add_argument(
129 '--format',
130 help='output format, defaults to "pretty"',
131 default='json',
132 choices=['json', 'pretty'],
133 )
134
135 args = parser.parse_args(self.argv)
136 self.list(args)