]> git.proxmox.com Git - ceph.git/blame - ceph/src/ceph-volume/ceph_volume/devices/lvm/prepare.py
bump version to 12.1.4-pve1
[ceph.git] / ceph / src / ceph-volume / ceph_volume / devices / lvm / prepare.py
CommitLineData
d2e6a577
FG
1from __future__ import print_function
2import json
3import os
4from textwrap import dedent
5from ceph_volume.util import prepare as prepare_utils
6from ceph_volume.util import system
7from ceph_volume import conf, decorators
8from . import api
9from .common import prepare_parser
10
11
12def canonical_device_path(device):
13 """
14 Ensure that a device is canonical (full path) and that it exists so that
15 it can be used throughout the prepare/activate process
16 """
17 # FIXME: this is obviously super naive
18 inferred = os.path.join('/dev', device)
19 if os.path.exists(os.path.abspath(device)):
20 return device
21 elif os.path.exists(inferred):
22 return inferred
23 raise RuntimeError('Selected device does not exist: %s' % device)
24
25
26def prepare_filestore(device, journal, secrets, id_=None, fsid=None):
27 """
28 :param device: The name of the volume group or lvm to work with
29 :param journal: similar to device but can also be a regular/plain disk
30 :param secrets: A dict with the secrets needed to create the osd (e.g. cephx)
31 :param id_: The OSD id
32 :param fsid: The OSD fsid, also known as the OSD UUID
33 """
34 cephx_secret = secrets.get('cephx_secret', prepare_utils.create_key())
35 json_secrets = json.dumps(secrets)
36
37 # allow re-using an existing fsid, in case prepare failed
38 fsid = fsid or system.generate_uuid()
39 # allow re-using an id, in case a prepare failed
40 osd_id = id_ or prepare_utils.create_id(fsid, json_secrets)
41 # create the directory
42 prepare_utils.create_path(osd_id)
43 # format the device
44 prepare_utils.format_device(device)
45 # mount the data device
46 prepare_utils.mount_osd(device, osd_id)
47 # symlink the journal
48 prepare_utils.link_journal(journal, osd_id)
49 # get the latest monmap
50 prepare_utils.get_monmap(osd_id)
51 # prepare the osd filesystem
52 prepare_utils.osd_mkfs(osd_id, fsid)
53 # write the OSD keyring if it doesn't exist already
54 prepare_utils.write_keyring(osd_id, cephx_secret)
55
56
57def prepare_bluestore():
58 raise NotImplemented()
59
60
61class Prepare(object):
62
63 help = 'Format an LVM device and associate it with an OSD'
64
65 def __init__(self, argv):
66 self.argv = argv
67
68 @decorators.needs_root
69 def prepare(self, args):
70 # FIXME we don't allow re-using a keyring, we always generate one for the
71 # OSD, this needs to be fixed. This could either be a file (!) or a string
72 # (!!) or some flags that we would need to compound into a dict so that we
73 # can convert to JSON (!!!)
74 secrets = {'cephx_secret': prepare_utils.create_key()}
75
76 cluster_fsid = conf.ceph.get('global', 'fsid')
77 fsid = args.osd_fsid or system.generate_uuid()
78 #osd_id = args.osd_id or prepare_utils.create_id(fsid)
79 # allow re-using an id, in case a prepare failed
80 osd_id = args.osd_id or prepare_utils.create_id(fsid, json.dumps(secrets))
81 journal_name = "journal_%s" % fsid
82 osd_name = "osd_%s" % fsid
83
84 if args.filestore:
85 data_vg = api.get_vg(vg_name=args.data)
86 data_lv = api.get_lv(lv_name=args.data)
87 journal_vg = api.get_vg(vg_name=args.journal)
88 journal_lv = api.get_lv(lv_name=args.journal)
89 journal_device = None
90 # it is possible to pass a device as a journal that is not
91 # an actual logical volume (or group)
92 if not args.journal:
93 if data_lv:
94 raise RuntimeError('--journal is required when not using a vg for OSD data')
95 # collocated: carve out the journal from the data vg
96 if data_vg:
97 journal_lv = api.create_lv(
98 name=journal_name,
99 group=data_vg.name,
100 size=args.journal_size,
101 osd_fsid=fsid,
102 osd_id=osd_id,
103 type='journal',
104 cluster_fsid=cluster_fsid
105 )
106
107 # if a volume group was defined for the journal create that first
108 if journal_vg:
109 journal_lv = api.create_lv(
110 name=journal_name,
111 group=args.journal,
112 size=args.journal_size,
113 osd_fsid=fsid,
114 osd_id=osd_id,
115 type='journal',
116 cluster_fsid=cluster_fsid
117 )
118 if journal_lv:
119 journal_device = journal_lv.lv_path
120 # The journal is probably a device, not in LVM
121 elif args.journal:
122 journal_device = canonical_device_path(args.journal)
123 # At this point we must have a journal_lv or a journal device
124 # now create the osd from the group if that was found
125 if data_vg:
126 # XXX make sure that a there aren't more OSDs than physical
127 # devices from this volume group
128 data_lv = api.create_lv(
129 name=osd_name,
130 group=args.data,
131 osd_fsid=fsid,
132 osd_id=osd_id,
133 type='data',
134 journal_device=journal_device,
135 cluster_fsid=cluster_fsid
136 )
137 # we must have either an existing data_lv or a newly created, so lets make
138 # sure that the tags are correct
139 if not data_lv:
140 raise RuntimeError('no data logical volume found with: %s' % args.data)
141 data_lv.set_tags({
142 'ceph.type': 'data',
143 'ceph.osd_fsid': fsid,
144 'ceph.osd_id': osd_id,
145 'ceph.cluster_fsid': cluster_fsid,
146 'ceph.journal_device': journal_device,
147 'ceph.data_device': data_lv.lv_path,
148 })
149
150 prepare_filestore(
151 data_lv.lv_path,
152 journal_device,
153 secrets,
154 id_=osd_id,
155 fsid=fsid,
156 )
157 elif args.bluestore:
158 prepare_bluestore(args)
159
160 def main(self):
161 sub_command_help = dedent("""
162 Prepare an OSD by assigning an ID and FSID, registering them with the
163 cluster with an ID and FSID, formatting and mounting the volume, and
164 finally by adding all the metadata to the logical volumes using LVM
165 tags, so that it can later be discovered.
166
167 Once the OSD is ready, an ad-hoc systemd unit will be enabled so that
168 it can later get activated and the OSD daemon can get started.
169
170 Most basic Usage looks like (journal will be collocated from the same volume group):
171
172 ceph-volume lvm prepare --data {volume group name}
173
174
175 Example calls for supported scenarios:
176
177 Dedicated volume group for Journal(s)
178 -------------------------------------
179
180 Existing logical volume (lv) or device:
181
182 ceph-volume lvm prepare --data {logical volume} --journal /path/to/{lv}|{device}
183
184 Or:
185
186 ceph-volume lvm prepare --data {data volume group} --journal {journal volume group}
187
188 Collocated (same group) for data and journal
189 --------------------------------------------
190
191 ceph-volume lvm prepare --data {volume group}
192
193 """)
194 parser = prepare_parser(
195 prog='ceph-volume lvm prepare',
196 description=sub_command_help,
197 )
198 if len(self.argv) == 0:
199 print(sub_command_help)
200 return
201 args = parser.parse_args(self.argv)
202 self.prepare(args)