]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | from __future__ import print_function |
2 | import argparse | |
3 | import json | |
4 | import logging | |
5 | from textwrap import dedent | |
6 | from ceph_volume import decorators, process | |
7 | ||
8 | ||
9 | logger = logging.getLogger(__name__) | |
10 | ||
11 | def 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 | ||
22 | class 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) |