1 from ceph_volume
.util
import arg_validators
, disk
2 from ceph_volume
import process
, conf
3 from ceph_volume
import terminal
4 from ceph_volume
.devices
.lvm
.zap
import Zap
7 def rollback_osd(args
, osd_id
=None):
9 When the process of creating or preparing fails, the OSD needs to be
10 destroyed so that the ID can be reused. This prevents from leaving the ID
11 around as "used" on the monitor, which can cause confusion if expecting
14 The usage of `destroy-new` allows this to be done without requiring the
15 admin keyring (otherwise needed for destroy and purge commands)
18 # it means that it wasn't generated, so there is nothing to rollback here
21 # once here, this is an error condition that needs to be rolled back
22 terminal
.error('Was unable to complete a new OSD, will rollback changes')
24 bootstrap_keyring
= '/var/lib/ceph/bootstrap-osd/%s.keyring' % conf
.cluster
27 '--cluster', conf
.cluster
,
28 '--name', 'client.bootstrap-osd',
29 '--keyring', bootstrap_keyring
,
30 'osd', 'purge-new', osd_name
% osd_id
,
31 '--yes-i-really-mean-it',
35 Zap(['--destroy', '--osd-id', osd_id
]).main()
40 'help': 'OSD data path. A physical device or logical volume',
42 'type': arg_validators
.ValidDataDevice(as_string
=True),
47 'help': 'Size of data LV in case a device was passed in --data',
49 'type': disk
.Size
.parse
52 'help': ('Intended number of slots on data device. The new OSD gets one'
53 'of those slots or 1/nth of the available capacity'),
58 'help': 'Reuse an existing OSD id',
60 'type': arg_validators
.valid_osd_id
,
63 'help': 'Reuse an existing OSD fsid',
67 'help': 'Specify the cluster fsid, useful when no ceph.conf is available',
70 '--crush-device-class': {
71 'dest': 'crush_device_class',
72 'help': 'Crush device class to assign this OSD to',
76 'action': 'store_true',
77 'help': 'Enable device encryption via dm-crypt',
81 'action': 'store_true',
82 'help': 'Skip creating and enabling systemd units and starting OSD services when activating',
88 'action': 'store_true',
89 'help': 'Use the bluestore objectstore',
93 'help': 'Path to bluestore block.db logical volume or device',
94 'type': arg_validators
.ValidDevice(as_string
=True),
97 'dest': 'block_db_size',
98 'help': 'Size of block.db LV in case device was passed in --block.db',
100 'type': disk
.Size
.parse
102 '--block.db-slots': {
103 'dest': 'block_db_slots',
104 'help': ('Intended number of slots on db device. The new OSD gets one'
105 'of those slots or 1/nth of the available capacity'),
111 'help': 'Path to bluestore block.wal logical volume or device',
112 'type': arg_validators
.ValidDevice(as_string
=True),
114 '--block.wal-size': {
115 'dest': 'block_wal_size',
116 'help': 'Size of block.wal LV in case device was passed in --block.wal',
118 'type': disk
.Size
.parse
120 '--block.wal-slots': {
121 'dest': 'block_wal_slots',
122 'help': ('Intended number of slots on wal device. The new OSD gets one'
123 'of those slots or 1/nth of the available capacity'),
130 def get_default_args():
132 def format_name(name
):
133 return name
.strip('-').replace('-', '_').replace('.', '_')
134 for argset
in (common_args
, bluestore_args
):
135 defaults
.update({format_name(name
): val
.get('default', None) for name
, val
in argset
.items()})
139 def common_parser(prog
, description
):
141 Both prepare and create share the same parser, those are defined here to
144 parser
= argparse
.ArgumentParser(
146 formatter_class
=argparse
.RawDescriptionHelpFormatter
,
147 description
=description
,
150 bluestore_group
= parser
.add_argument_group('bluestore')
152 for name
, kwargs
in common_args
.items():
153 parser
.add_argument(name
, **kwargs
)
155 for name
, kwargs
in bluestore_args
.items():
156 bluestore_group
.add_argument(name
, **kwargs
)
158 # Do not parse args, so that consumers can do something before the args get
159 # parsed triggering argparse behavior
163 create_parser
= common_parser
# noqa
164 prepare_parser
= common_parser
# noqa