]>
Commit | Line | Data |
---|---|---|
f91f0fd5 | 1 | from ceph_volume.util import arg_validators, disk |
11fdf7f2 | 2 | from ceph_volume import process, conf |
b32b8144 | 3 | from ceph_volume import terminal |
20effc67 | 4 | from ceph_volume.devices.lvm.zap import Zap |
d2e6a577 FG |
5 | import argparse |
6 | ||
7 | ||
b32b8144 FG |
8 | def rollback_osd(args, osd_id=None): |
9 | """ | |
11fdf7f2 | 10 | When the process of creating or preparing fails, the OSD needs to be |
20effc67 | 11 | destroyed so that the ID can be reused. This prevents from leaving the ID |
11fdf7f2 TL |
12 | around as "used" on the monitor, which can cause confusion if expecting |
13 | sequential OSD IDs. | |
14 | ||
15 | The usage of `destroy-new` allows this to be done without requiring the | |
16 | admin keyring (otherwise needed for destroy and purge commands) | |
b32b8144 FG |
17 | """ |
18 | if not osd_id: | |
19 | # it means that it wasn't generated, so there is nothing to rollback here | |
20 | return | |
21 | ||
22 | # once here, this is an error condition that needs to be rolled back | |
23 | terminal.error('Was unable to complete a new OSD, will rollback changes') | |
24 | osd_name = 'osd.%s' | |
11fdf7f2 TL |
25 | bootstrap_keyring = '/var/lib/ceph/bootstrap-osd/%s.keyring' % conf.cluster |
26 | cmd = [ | |
27 | 'ceph', | |
28 | '--cluster', conf.cluster, | |
29 | '--name', 'client.bootstrap-osd', | |
30 | '--keyring', bootstrap_keyring, | |
31 | 'osd', 'purge-new', osd_name % osd_id, | |
32 | '--yes-i-really-mean-it', | |
33 | ] | |
34 | ||
35 | process.run(cmd) | |
20effc67 | 36 | Zap(['--destroy', '--osd-id', osd_id]).main() |
b32b8144 FG |
37 | |
38 | ||
f91f0fd5 TL |
39 | common_args = { |
40 | '--data': { | |
41 | 'help': 'OSD data path. A physical device or logical volume', | |
42 | 'required': True, | |
43 | 'type': arg_validators.ValidDevice(as_string=True), | |
44 | #'default':, | |
45 | #'type':, | |
46 | }, | |
47 | '--data-size': { | |
48 | 'help': 'Size of data LV in case a device was passed in --data', | |
49 | 'default': '0', | |
50 | 'type': disk.Size.parse | |
51 | }, | |
52 | '--data-slots': { | |
53 | 'help': ('Intended number of slots on data device. The new OSD gets one' | |
54 | 'of those slots or 1/nth of the available capacity'), | |
55 | 'type': int, | |
56 | 'default': 1, | |
57 | }, | |
58 | '--osd-id': { | |
59 | 'help': 'Reuse an existing OSD id', | |
60 | 'default': None, | |
20effc67 | 61 | 'type': arg_validators.valid_osd_id, |
f91f0fd5 TL |
62 | }, |
63 | '--osd-fsid': { | |
64 | 'help': 'Reuse an existing OSD fsid', | |
65 | 'default': None, | |
66 | }, | |
67 | '--cluster-fsid': { | |
68 | 'help': 'Specify the cluster fsid, useful when no ceph.conf is available', | |
69 | 'default': None, | |
70 | }, | |
71 | '--crush-device-class': { | |
72 | 'dest': 'crush_device_class', | |
73 | 'help': 'Crush device class to assign this OSD to', | |
20effc67 | 74 | 'default': "", |
f91f0fd5 TL |
75 | }, |
76 | '--dmcrypt': { | |
77 | 'action': 'store_true', | |
78 | 'help': 'Enable device encryption via dm-crypt', | |
79 | }, | |
80 | '--no-systemd': { | |
81 | 'dest': 'no_systemd', | |
82 | 'action': 'store_true', | |
83 | 'help': 'Skip creating and enabling systemd units and starting OSD services when activating', | |
84 | }, | |
85 | } | |
86 | ||
87 | bluestore_args = { | |
88 | '--bluestore': { | |
89 | 'action': 'store_true', | |
90 | 'help': 'Use the bluestore objectstore', | |
91 | }, | |
92 | '--block.db': { | |
93 | 'dest': 'block_db', | |
94 | 'help': 'Path to bluestore block.db logical volume or device', | |
1d09f67e | 95 | 'type': arg_validators.ValidDevice(as_string=True), |
f91f0fd5 TL |
96 | }, |
97 | '--block.db-size': { | |
98 | 'dest': 'block_db_size', | |
99 | 'help': 'Size of block.db LV in case device was passed in --block.db', | |
100 | 'default': '0', | |
101 | 'type': disk.Size.parse | |
102 | }, | |
103 | '--block.db-slots': { | |
104 | 'dest': 'block_db_slots', | |
105 | 'help': ('Intended number of slots on db device. The new OSD gets one' | |
106 | 'of those slots or 1/nth of the available capacity'), | |
107 | 'type': int, | |
108 | 'default': 1, | |
109 | }, | |
110 | '--block.wal': { | |
111 | 'dest': 'block_wal', | |
112 | 'help': 'Path to bluestore block.wal logical volume or device', | |
1d09f67e | 113 | 'type': arg_validators.ValidDevice(as_string=True), |
f91f0fd5 TL |
114 | }, |
115 | '--block.wal-size': { | |
116 | 'dest': 'block_wal_size', | |
117 | 'help': 'Size of block.wal LV in case device was passed in --block.wal', | |
118 | 'default': '0', | |
119 | 'type': disk.Size.parse | |
120 | }, | |
121 | '--block.wal-slots': { | |
122 | 'dest': 'block_wal_slots', | |
123 | 'help': ('Intended number of slots on wal device. The new OSD gets one' | |
124 | 'of those slots or 1/nth of the available capacity'), | |
125 | 'type': int, | |
126 | 'default': 1, | |
127 | }, | |
128 | } | |
129 | ||
130 | filestore_args = { | |
131 | '--filestore': { | |
132 | 'action': 'store_true', | |
133 | 'help': 'Use the filestore objectstore', | |
134 | }, | |
135 | '--journal': { | |
136 | 'help': 'A logical volume (vg_name/lv_name), or path to a device', | |
1d09f67e | 137 | 'type': arg_validators.ValidDevice(as_string=True), |
f91f0fd5 TL |
138 | }, |
139 | '--journal-size': { | |
140 | 'help': 'Size of journal LV in case a raw block device was passed in --journal', | |
141 | 'default': '0', | |
142 | 'type': disk.Size.parse | |
143 | }, | |
144 | '--journal-slots': { | |
145 | 'help': ('Intended number of slots on journal device. The new OSD gets one' | |
146 | 'of those slots or 1/nth of the available capacity'), | |
147 | 'type': int, | |
148 | 'default': 1, | |
149 | }, | |
150 | } | |
151 | ||
152 | def get_default_args(): | |
153 | defaults = {} | |
154 | def format_name(name): | |
155 | return name.strip('-').replace('-', '_').replace('.', '_') | |
156 | for argset in (common_args, filestore_args, bluestore_args): | |
157 | defaults.update({format_name(name): val.get('default', None) for name, val in argset.items()}) | |
158 | return defaults | |
159 | ||
160 | ||
d2e6a577 FG |
161 | def common_parser(prog, description): |
162 | """ | |
163 | Both prepare and create share the same parser, those are defined here to | |
164 | avoid duplication | |
165 | """ | |
166 | parser = argparse.ArgumentParser( | |
167 | prog=prog, | |
168 | formatter_class=argparse.RawDescriptionHelpFormatter, | |
169 | description=description, | |
170 | ) | |
3a9019d9 | 171 | |
3a9019d9 FG |
172 | filestore_group = parser.add_argument_group('filestore') |
173 | bluestore_group = parser.add_argument_group('bluestore') | |
174 | ||
f91f0fd5 TL |
175 | for name, kwargs in common_args.items(): |
176 | parser.add_argument(name, **kwargs) | |
92f5a8d4 | 177 | |
f91f0fd5 TL |
178 | for name, kwargs in bluestore_args.items(): |
179 | bluestore_group.add_argument(name, **kwargs) | |
92f5a8d4 | 180 | |
f91f0fd5 TL |
181 | for name, kwargs in filestore_args.items(): |
182 | filestore_group.add_argument(name, **kwargs) | |
94b18763 | 183 | |
d2e6a577 FG |
184 | # Do not parse args, so that consumers can do something before the args get |
185 | # parsed triggering argparse behavior | |
186 | return parser | |
187 | ||
188 | ||
189 | create_parser = common_parser # noqa | |
190 | prepare_parser = common_parser # noqa |