]>
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 = [] | |
33 | out, err, ret = process.call([ | |
34 | 'lsblk', '--paths', '--nodeps', '--output=NAME', '--noheadings' | |
35 | ]) | |
36 | assert not ret | |
37 | devs = out | |
38 | result = {} | |
39 | for dev in devs: | |
40 | logger.debug('Examining %s' % dev) | |
41 | # bluestore? | |
42 | out, err, ret = process.call([ | |
43 | 'ceph-bluestore-tool', 'show-label', | |
44 | '--dev', dev]) | |
45 | if ret: | |
46 | logger.debug('No label on %s' % dev) | |
47 | continue | |
48 | oj = json.loads(''.join(out)) | |
49 | if dev not in oj: | |
50 | continue | |
51 | if oj[dev]['description'] != 'main': | |
52 | # ignore non-main devices, for now | |
53 | continue | |
54 | whoami = oj[dev]['whoami'] | |
55 | result[whoami] = { | |
56 | 'type': 'bluestore', | |
57 | 'osd_id': int(whoami), | |
58 | } | |
59 | for f in ['osd_uuid', 'ceph_fsid']: | |
60 | result[whoami][f] = oj[dev][f] | |
61 | result[whoami]['device'] = dev | |
62 | return result | |
63 | ||
64 | @decorators.needs_root | |
65 | def list(self, args): | |
66 | report = self.generate(args.device) | |
67 | if args.format == 'json': | |
68 | print(json.dumps(report, indent=4, sort_keys=True)) | |
69 | else: | |
70 | if not report: | |
71 | raise SystemExit('No valid Ceph devices found') | |
72 | raise RuntimeError('not implemented yet') | |
73 | ||
74 | def main(self): | |
75 | sub_command_help = dedent(""" | |
76 | List OSDs on raw devices with raw device labels (usually the first | |
77 | block of the device). | |
78 | ||
79 | Full listing of all identifiable (currently, BlueStore) OSDs | |
80 | on raw devices: | |
81 | ||
82 | ceph-volume raw list | |
83 | ||
84 | List a particular device, reporting all metadata about it:: | |
85 | ||
86 | ceph-volume raw list /dev/sda1 | |
87 | ||
88 | """) | |
89 | parser = argparse.ArgumentParser( | |
90 | prog='ceph-volume raw list', | |
91 | formatter_class=argparse.RawDescriptionHelpFormatter, | |
92 | description=sub_command_help, | |
93 | ) | |
94 | ||
95 | parser.add_argument( | |
96 | 'device', | |
97 | metavar='DEVICE', | |
98 | nargs='*', | |
99 | help='Path to a device like /dev/sda1' | |
100 | ) | |
101 | ||
102 | parser.add_argument( | |
103 | '--format', | |
104 | help='output format, defaults to "pretty"', | |
105 | default='json', | |
106 | choices=['json', 'pretty'], | |
107 | ) | |
108 | ||
109 | args = parser.parse_args(self.argv) | |
110 | self.list(args) |