]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/driver/rados/config/realm.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / driver / rados / config / realm.cc
CommitLineData
1e59de90
TL
1// vim: ts=8 sw=2 smarttab ft=cpp
2
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2022 Red Hat, Inc.
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include "common/dout.h"
16#include "common/errno.h"
17#include "rgw_realm_watcher.h"
18#include "rgw_zone.h"
19#include "driver/rados/config/store.h"
20
21#include "impl.h"
22
23namespace rgw::rados {
24
25// realm oids
26constexpr std::string_view realm_names_oid_prefix = "realms_names.";
27constexpr std::string_view realm_info_oid_prefix = "realms.";
28constexpr std::string_view realm_control_oid_suffix = ".control";
29constexpr std::string_view default_realm_info_oid = "default.realm";
30
31static std::string realm_info_oid(std::string_view realm_id)
32{
33 return string_cat_reserve(realm_info_oid_prefix, realm_id);
34}
35static std::string realm_name_oid(std::string_view realm_id)
36{
37 return string_cat_reserve(realm_names_oid_prefix, realm_id);
38}
39static std::string realm_control_oid(std::string_view realm_id)
40{
41 return string_cat_reserve(realm_info_oid_prefix, realm_id,
42 realm_control_oid_suffix);
43}
44static std::string default_realm_oid(const ceph::common::ConfigProxy& conf)
45{
46 return std::string{name_or_default(conf->rgw_default_realm_info_oid,
47 default_realm_info_oid)};
48}
49
50
51int RadosConfigStore::write_default_realm_id(const DoutPrefixProvider* dpp,
52 optional_yield y, bool exclusive,
53 std::string_view realm_id)
54{
55 const auto& pool = impl->realm_pool;
56 const auto oid = default_realm_oid(dpp->get_cct()->_conf);
57 const auto create = exclusive ? Create::MustNotExist : Create::MayExist;
58
59 RGWDefaultSystemMetaObjInfo default_info;
60 default_info.default_id = realm_id;
61
62 return impl->write(dpp, y, pool, oid, create, default_info, nullptr);
63}
64
65int RadosConfigStore::read_default_realm_id(const DoutPrefixProvider* dpp,
66 optional_yield y,
67 std::string& realm_id)
68{
69 const auto& pool = impl->realm_pool;
70 const auto oid = default_realm_oid(dpp->get_cct()->_conf);
71
72 RGWDefaultSystemMetaObjInfo default_info;
73 int r = impl->read(dpp, y, pool, oid, default_info, nullptr);
74 if (r >= 0) {
75 realm_id = default_info.default_id;
76 }
77 return r;
78}
79
80int RadosConfigStore::delete_default_realm_id(const DoutPrefixProvider* dpp,
81 optional_yield y)
82{
83 const auto& pool = impl->realm_pool;
84 const auto oid = default_realm_oid(dpp->get_cct()->_conf);
85
86 return impl->remove(dpp, y, pool, oid, nullptr);
87}
88
89
90class RadosRealmWriter : public sal::RealmWriter {
91 ConfigImpl* impl;
92 RGWObjVersionTracker objv;
93 std::string realm_id;
94 std::string realm_name;
95 public:
96 RadosRealmWriter(ConfigImpl* impl, RGWObjVersionTracker objv,
97 std::string_view realm_id, std::string_view realm_name)
98 : impl(impl), objv(std::move(objv)),
99 realm_id(realm_id), realm_name(realm_name)
100 {
101 }
102
103 int write(const DoutPrefixProvider* dpp, optional_yield y,
104 const RGWRealm& info) override
105 {
106 if (realm_id != info.get_id() || realm_name != info.get_name()) {
107 return -EINVAL; // can't modify realm id or name directly
108 }
109
110 const auto& pool = impl->realm_pool;
111 const auto info_oid = realm_info_oid(info.get_id());
112 return impl->write(dpp, y, pool, info_oid, Create::MustExist, info, &objv);
113 }
114
115 int rename(const DoutPrefixProvider* dpp, optional_yield y,
116 RGWRealm& info, std::string_view new_name) override
117 {
118 if (realm_id != info.get_id() || realm_name != info.get_name()) {
119 return -EINVAL; // can't modify realm id or name directly
120 }
121 if (new_name.empty()) {
122 ldpp_dout(dpp, 0) << "realm cannot have an empty name" << dendl;
123 return -EINVAL;
124 }
125
126 const auto& pool = impl->realm_pool;
127 const auto name = RGWNameToId{info.get_id()};
128 const auto info_oid = realm_info_oid(info.get_id());
129 const auto old_oid = realm_name_oid(info.get_name());
130 const auto new_oid = realm_name_oid(new_name);
131
132 // link the new name
133 RGWObjVersionTracker new_objv;
134 new_objv.generate_new_write_ver(dpp->get_cct());
135 int r = impl->write(dpp, y, pool, new_oid, Create::MustNotExist,
136 name, &new_objv);
137 if (r < 0) {
138 return r;
139 }
140
141 // write the info with updated name
142 info.set_name(std::string{new_name});
143 r = impl->write(dpp, y, pool, info_oid, Create::MustExist, info, &objv);
144 if (r < 0) {
145 // on failure, unlink the new name
146 (void) impl->remove(dpp, y, pool, new_oid, &new_objv);
147 return r;
148 }
149
150 // unlink the old name
151 (void) impl->remove(dpp, y, pool, old_oid, nullptr);
152
153 realm_name = new_name;
154 return 0;
155 }
156
157 int remove(const DoutPrefixProvider* dpp, optional_yield y) override
158 {
159 const auto& pool = impl->realm_pool;
160 const auto info_oid = realm_info_oid(realm_id);
161 int r = impl->remove(dpp, y, pool, info_oid, &objv);
162 if (r < 0) {
163 return r;
164 }
165 const auto name_oid = realm_name_oid(realm_name);
166 (void) impl->remove(dpp, y, pool, name_oid, nullptr);
167 const auto control_oid = realm_control_oid(realm_id);
168 (void) impl->remove(dpp, y, pool, control_oid, nullptr);
169 return 0;
170 }
171}; // RadosRealmWriter
172
173
174int RadosConfigStore::create_realm(const DoutPrefixProvider* dpp,
175 optional_yield y, bool exclusive,
176 const RGWRealm& info,
177 std::unique_ptr<sal::RealmWriter>* writer)
178{
179 if (info.get_id().empty()) {
180 ldpp_dout(dpp, 0) << "realm cannot have an empty id" << dendl;
181 return -EINVAL;
182 }
183 if (info.get_name().empty()) {
184 ldpp_dout(dpp, 0) << "realm cannot have an empty name" << dendl;
185 return -EINVAL;
186 }
187
188 const auto& pool = impl->realm_pool;
189 const auto create = exclusive ? Create::MustNotExist : Create::MayExist;
190
191 // write the realm info
192 const auto info_oid = realm_info_oid(info.get_id());
193 RGWObjVersionTracker objv;
194 objv.generate_new_write_ver(dpp->get_cct());
195
196 int r = impl->write(dpp, y, pool, info_oid, create, info, &objv);
197 if (r < 0) {
198 return r;
199 }
200
201 // write the realm name
202 const auto name_oid = realm_name_oid(info.get_name());
203 const auto name = RGWNameToId{info.get_id()};
204 RGWObjVersionTracker name_objv;
205 name_objv.generate_new_write_ver(dpp->get_cct());
206
207 r = impl->write(dpp, y, pool, name_oid, create, name, &name_objv);
208 if (r < 0) {
209 (void) impl->remove(dpp, y, pool, info_oid, &objv);
210 return r;
211 }
212
213 // create control object for watch/notify
214 const auto control_oid = realm_control_oid(info.get_id());
215 bufferlist empty_bl;
216 r = impl->write(dpp, y, pool, control_oid, Create::MayExist,
217 empty_bl, nullptr);
218 if (r < 0) {
219 (void) impl->remove(dpp, y, pool, name_oid, &name_objv);
220 (void) impl->remove(dpp, y, pool, info_oid, &objv);
221 return r;
222 }
223
224 if (writer) {
225 *writer = std::make_unique<RadosRealmWriter>(
226 impl.get(), std::move(objv), info.get_id(), info.get_name());
227 }
228 return 0;
229}
230
231int RadosConfigStore::read_realm_by_id(const DoutPrefixProvider* dpp,
232 optional_yield y,
233 std::string_view realm_id,
234 RGWRealm& info,
235 std::unique_ptr<sal::RealmWriter>* writer)
236{
237 const auto& pool = impl->realm_pool;
238 const auto info_oid = realm_info_oid(realm_id);
239 RGWObjVersionTracker objv;
240 int r = impl->read(dpp, y, pool, info_oid, info, &objv);
241 if (r < 0) {
242 return r;
243 }
244
245 if (writer) {
246 *writer = std::make_unique<RadosRealmWriter>(
247 impl.get(), std::move(objv), info.get_id(), info.get_name());
248 }
249 return 0;
250}
251
252int RadosConfigStore::read_realm_by_name(const DoutPrefixProvider* dpp,
253 optional_yield y,
254 std::string_view realm_name,
255 RGWRealm& info,
256 std::unique_ptr<sal::RealmWriter>* writer)
257{
258 const auto& pool = impl->realm_pool;
259
260 // look up realm id by name
261 RGWNameToId name;
262 const auto name_oid = realm_name_oid(realm_name);
263 int r = impl->read(dpp, y, pool, name_oid, name, nullptr);
264 if (r < 0) {
265 return r;
266 }
267
268 const auto info_oid = realm_info_oid(name.obj_id);
269 RGWObjVersionTracker objv;
270 r = impl->read(dpp, y, pool, info_oid, info, &objv);
271 if (r < 0) {
272 return r;
273 }
274
275 if (writer) {
276 *writer = std::make_unique<RadosRealmWriter>(
277 impl.get(), std::move(objv), info.get_id(), info.get_name());
278 }
279 return 0;
280}
281
282int RadosConfigStore::read_default_realm(const DoutPrefixProvider* dpp,
283 optional_yield y,
284 RGWRealm& info,
285 std::unique_ptr<sal::RealmWriter>* writer)
286{
287 const auto& pool = impl->realm_pool;
288
289 // read default realm id
290 RGWDefaultSystemMetaObjInfo default_info;
291 const auto default_oid = default_realm_oid(dpp->get_cct()->_conf);
292 int r = impl->read(dpp, y, pool, default_oid, default_info, nullptr);
293 if (r < 0) {
294 return r;
295 }
296
297 const auto info_oid = realm_info_oid(default_info.default_id);
298 RGWObjVersionTracker objv;
299 r = impl->read(dpp, y, pool, info_oid, info, &objv);
300 if (r < 0) {
301 return r;
302 }
303
304 if (writer) {
305 *writer = std::make_unique<RadosRealmWriter>(
306 impl.get(), std::move(objv), info.get_id(), info.get_name());
307 }
308 return 0;
309}
310
311int RadosConfigStore::read_realm_id(const DoutPrefixProvider* dpp,
312 optional_yield y,
313 std::string_view realm_name,
314 std::string& realm_id)
315{
316 const auto& pool = impl->realm_pool;
317 RGWNameToId name;
318
319 // look up realm id by name
320 const auto name_oid = realm_name_oid(realm_name);
321 int r = impl->read(dpp, y, pool, name_oid, name, nullptr);
322 if (r < 0) {
323 return r;
324 }
325 realm_id = std::move(name.obj_id);
326 return 0;
327}
328
329int RadosConfigStore::realm_notify_new_period(const DoutPrefixProvider* dpp,
330 optional_yield y,
331 const RGWPeriod& period)
332{
333 const auto& pool = impl->realm_pool;
334 const auto control_oid = realm_control_oid(period.get_realm());
335
336 bufferlist bl;
337 using ceph::encode;
338 // push the period to dependent zonegroups/zones
339 encode(RGWRealmNotify::ZonesNeedPeriod, bl);
340 encode(period, bl);
341 // reload the gateway with the new period
342 encode(RGWRealmNotify::Reload, bl);
343
344 constexpr uint64_t timeout_ms = 0;
345 return impl->notify(dpp, y, pool, control_oid, bl, timeout_ms);
346}
347
348int RadosConfigStore::list_realm_names(const DoutPrefixProvider* dpp,
349 optional_yield y,
350 const std::string& marker,
351 std::span<std::string> entries,
352 sal::ListResult<std::string>& result)
353{
354 const auto& pool = impl->realm_pool;
355 constexpr auto prefix = [] (std::string oid) -> std::string {
356 if (!oid.starts_with(realm_names_oid_prefix)) {
357 return {};
358 }
359 return oid.substr(realm_names_oid_prefix.size());
360 };
361 return impl->list(dpp, y, pool, marker, prefix, entries, result);
362}
363
364} // namespace rgw::rados