]>
git.proxmox.com Git - ceph.git/blob - ceph/src/ceph-volume/ceph_volume/devices/lvm/strategies/bluestore.py
1 from __future__
import print_function
4 from ceph_volume
.util
import disk
5 from ceph_volume
.api
import lvm
6 from . import validators
7 from ceph_volume
.devices
.lvm
.create
import Create
8 from ceph_volume
.util
import templates
11 class SingleType(object):
13 Support for all SSDs, or all HDDS
16 def __init__(self
, devices
, args
):
18 self
.devices
= devices
19 self
.hdds
= [device
for device
in devices
if device
.sys_api
['rotational'] == '1']
20 self
.ssds
= [device
for device
in devices
if device
.sys_api
['rotational'] == '0']
21 self
.computed
= {'osds': [], 'vgs': []}
25 def report_json(self
):
26 print(json
.dumps(self
.computed
, indent
=4, sort_keys
=True))
28 def report_pretty(self
):
30 string
+= templates
.total_osds
.format(
31 total_osds
=len(self
.hdds
) or len(self
.ssds
) * 2
33 string
+= templates
.osd_component_titles
35 for osd
in self
.computed
['osds']:
36 string
+= templates
.osd_header
37 string
+= templates
.osd_component
.format(
39 path
=osd
['data']['path'],
40 size
=osd
['data']['human_readable_size'],
41 percent
=osd
['data']['percentage'],
48 Ensure that the minimum requirements for this type of scenario is
49 met, raise an error if the provided devices would not work
51 # validate minimum size for all devices
52 validators
.minimum_device_size(self
.devices
)
56 Go through the rules needed to properly size the lvs, return
57 a dictionary with the result
59 osds
= self
.computed
['osds']
60 vgs
= self
.computed
['vgs']
61 for device
in self
.hdds
:
62 vgs
.append({'devices': [device
.abspath
], 'parts': 1})
63 osd
= {'data': {}, 'block.db': {}}
64 osd
['data']['path'] = device
.abspath
65 osd
['data']['size'] = device
.sys_api
['size']
66 osd
['data']['parts'] = 1
67 osd
['data']['percentage'] = 100
68 osd
['data']['human_readable_size'] = str(disk
.Size(b
=device
.sys_api
['size']))
71 for device
in self
.ssds
:
72 # TODO: creates 2 OSDs per device, make this configurable (env var?)
73 extents
= lvm
.sizing(device
.sys_api
['size'], parts
=2)
74 vgs
.append({'devices': [device
.abspath
], 'parts': 2})
76 osd
= {'data': {}, 'block.db': {}}
77 osd
['data']['path'] = device
.abspath
78 osd
['data']['size'] = extents
['sizes']
79 osd
['data']['parts'] = extents
['parts']
80 osd
['data']['percentage'] = 50
81 osd
['data']['human_readable_size'] = str(disk
.Size(b
=extents
['sizes']))
86 Create vgs/lvs from the incoming set of devices, assign their roles
87 (block, block.db, block.wal, etc..) and offload the OSD creation to
90 osd_vgs
= dict([(osd
['data']['path'], None) for osd
in self
.computed
['osds']])
92 # create the vgs first, mapping them to the device path
93 for osd
in self
.computed
['osds']:
94 vg
= osd_vgs
.get(osd
['data']['path'])
96 vg
= lvm
.create_vg(osd
['data']['path'])
97 osd_vgs
[osd
['data']['path']] = {'vg': vg
, 'parts': osd
['data']['parts']}
99 # create the lvs from the vgs captured in the beginning
100 for create
in osd_vgs
.values():
101 lvs
= lvm
.create_lvs(create
['vg'], parts
=create
['parts'], name_prefix
='osd-data')
102 vg_name
= create
['vg'].name
104 command
= ['--bluestore', '--data']
105 command
.append('%s/%s' % (vg_name
, lv
.name
))
106 if self
.args
.dmcrypt
:
107 command
.append('--dmcrypt')
108 if self
.args
.no_systemd
:
109 command
.append('--no-systemd')
110 if self
.args
.crush_device_class
:
111 command
.extend(['--crush-device-class', self
.args
.crush_device_class
])
113 Create(command
).main()
116 class MixedType(object):
118 def __init__(self
, devices
, args
):
120 self
.devices
= devices
121 self
.hdds
= [device
for device
in devices
if device
.sys_api
['rotational'] == '1']
122 self
.ssds
= [device
for device
in devices
if device
.sys_api
['rotational'] == '0']
123 self
.computed
= {'osds': [], 'vgs': []}
124 self
.block_db_size
= None
125 # For every HDD we get 1 block.db
126 self
.db_lvs
= len(self
.hdds
)
130 def report_json(self
):
131 print(json
.dumps(self
.computed
, indent
=4, sort_keys
=True))
133 def report_pretty(self
):
134 vg_extents
= lvm
.sizing(self
.total_ssd_size
.b
, parts
=self
.db_lvs
)
135 db_size
= str(disk
.Size(b
=(vg_extents
['sizes'])))
138 string
+= templates
.total_osds
.format(
139 total_osds
=len(self
.hdds
)
142 string
+= templates
.ssd_volume_group
.format(
144 total_lv_size
=str(self
.total_ssd_size
),
145 total_lvs
=vg_extents
['parts'],
146 block_lv_size
=db_size
,
147 block_db_devices
=', '.join([ssd
.abspath
for ssd
in self
.ssds
]),
148 lv_size
=str(disk
.Size(b
=(vg_extents
['sizes']))),
149 total_osds
=len(self
.hdds
)
152 string
+= templates
.osd_component_titles
153 for osd
in self
.computed
['osds']:
154 string
+= templates
.osd_header
155 string
+= templates
.osd_component
.format(
157 path
=osd
['data']['path'],
158 size
=osd
['data']['human_readable_size'],
159 percent
=osd
['data']['percentage'])
161 string
+= templates
.osd_component
.format(
163 path
='(volume-group/lv)',
164 size
=osd
['block.db']['human_readable_size'],
165 percent
=osd
['block.db']['percentage'])
170 osds
= self
.computed
['osds']
171 for device
in self
.hdds
:
172 osd
= {'data': {}, 'block.db': {}}
173 osd
['data']['path'] = device
.abspath
174 osd
['data']['size'] = device
.sys_api
['size']
175 osd
['data']['percentage'] = 100
176 osd
['data']['human_readable_size'] = str(disk
.Size(b
=(device
.sys_api
['size'])))
177 osd
['block.db']['path'] = None
178 osd
['block.db']['size'] = int(self
.block_db_size
.b
)
179 osd
['block.db']['human_readable_size'] = str(self
.block_db_size
)
180 osd
['block.db']['percentage'] = self
.vg_extents
['percentages']
183 self
.computed
['vgs'] = [{
184 'devices': [d
.abspath
for d
in self
.ssds
],
185 'parts': self
.db_lvs
,
186 'percentages': self
.vg_extents
['percentages'],
187 'sizes': self
.vg_extents
['sizes'],
188 'size': int(self
.total_ssd_size
.b
),
189 'human_readable_sizes': str(disk
.Size(b
=self
.vg_extents
['sizes'])),
190 'human_readable_size': str(self
.total_ssd_size
),
195 Create vgs/lvs from the incoming set of devices, assign their roles
196 (block, block.db, block.wal, etc..) and offload the OSD creation to
199 # create the single vg for all block.db lv's first
200 vg_info
= self
.computed
['vgs'][0]
201 vg
= lvm
.create_vg(vg_info
['devices'])
203 # now produce all the block.db lvs needed from that single vg
204 db_lvs
= lvm
.create_lvs(vg
, parts
=vg_info
['parts'], name_prefix
='osd-block-db')
206 # create the data lvs, and create the OSD with the matching block.db lvs from before
207 for osd
in self
.computed
['osds']:
208 vg
= lvm
.create_vg(osd
['data']['path'])
209 data_lv
= lvm
.create_lv('osd-data-%s' % str(uuid4()), vg
.name
)
213 '--data', "%s/%s" % (data_lv
.vg_name
, data_lv
.name
),
214 '--block.db', '%s/%s' % (db_lv
.vg_name
, db_lv
.name
)
216 if self
.args
.dmcrypt
:
217 command
.append('--dmcrypt')
218 if self
.args
.no_systemd
:
219 command
.append('--no-systemd')
220 if self
.args
.crush_device_class
:
221 command
.extend(['--crush-device-class', self
.args
.crush_device_class
])
223 Create(command
).main()
227 HDDs represent data devices, and solid state devices are for block.db,
228 make sure that the number of data devices would have enough LVs and
229 those LVs would be large enough to accommodate a block.db
231 # validate minimum size for all devices
232 validators
.minimum_device_size(self
.devices
)
234 # add all the size available in solid drives and divide it by the
235 # expected number of osds, the expected output should be larger than
236 # the minimum alllowed for block.db
237 self
.total_ssd_size
= disk
.Size(b
=0)
238 for ssd
in self
.ssds
:
239 self
.total_ssd_size
+= disk
.Size(b
=ssd
.sys_api
['size'])
241 self
.block_db_size
= self
.total_ssd_size
/ self
.db_lvs
242 self
.vg_extents
= lvm
.sizing(self
.total_ssd_size
.b
, parts
=self
.db_lvs
)
244 # min 2GB of block.db is allowed
245 msg
= 'Total solid size (%s) is not enough for block.db LVs larger than 2 GB'
246 if self
.block_db_size
< disk
.Size(gb
=2):
247 # use ad-hoc exception here
248 raise RuntimeError(msg
% self
.total_ssd_size
)