]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/driver/rados/config/zonegroup.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / driver / rados / config / zonegroup.cc
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_zone.h"
18 #include "driver/rados/config/store.h"
19
20 #include "impl.h"
21
22 namespace rgw::rados {
23
24 // zonegroup oids
25 constexpr std::string_view zonegroup_names_oid_prefix = "zonegroups_names.";
26 constexpr std::string_view zonegroup_info_oid_prefix = "zonegroup_info.";
27 constexpr std::string_view default_zonegroup_info_oid = "default.zonegroup";
28
29 static std::string zonegroup_info_oid(std::string_view zonegroup_id)
30 {
31 return string_cat_reserve(zonegroup_info_oid_prefix, zonegroup_id);
32 }
33 static std::string zonegroup_name_oid(std::string_view zonegroup_id)
34 {
35 return string_cat_reserve(zonegroup_names_oid_prefix, zonegroup_id);
36 }
37 static std::string default_zonegroup_oid(const ceph::common::ConfigProxy& conf,
38 std::string_view realm_id)
39 {
40 const auto prefix = name_or_default(conf->rgw_default_zonegroup_info_oid,
41 default_zonegroup_info_oid);
42 return fmt::format("{}.{}", prefix, realm_id);
43 }
44
45
46 int RadosConfigStore::write_default_zonegroup_id(const DoutPrefixProvider* dpp,
47 optional_yield y,
48 bool exclusive,
49 std::string_view realm_id,
50 std::string_view zonegroup_id)
51 {
52 const auto& pool = impl->zonegroup_pool;
53 const auto oid = default_zonegroup_oid(dpp->get_cct()->_conf, realm_id);
54 const auto create = exclusive ? Create::MustNotExist : Create::MayExist;
55
56 RGWDefaultSystemMetaObjInfo default_info;
57 default_info.default_id = zonegroup_id;
58
59 return impl->write(dpp, y, pool, oid, create, default_info, nullptr);
60 }
61
62 int RadosConfigStore::read_default_zonegroup_id(const DoutPrefixProvider* dpp,
63 optional_yield y,
64 std::string_view realm_id,
65 std::string& zonegroup_id)
66 {
67 const auto& pool = impl->zonegroup_pool;
68 const auto oid = default_zonegroup_oid(dpp->get_cct()->_conf, realm_id);
69
70 RGWDefaultSystemMetaObjInfo default_info;
71 int r = impl->read(dpp, y, pool, oid, default_info, nullptr);
72 if (r >= 0) {
73 zonegroup_id = default_info.default_id;
74 }
75 return r;
76 }
77
78 int RadosConfigStore::delete_default_zonegroup_id(const DoutPrefixProvider* dpp,
79 optional_yield y,
80 std::string_view realm_id)
81 {
82 const auto& pool = impl->zonegroup_pool;
83 const auto oid = default_zonegroup_oid(dpp->get_cct()->_conf, realm_id);
84 return impl->remove(dpp, y, pool, oid, nullptr);
85 }
86
87
88 class RadosZoneGroupWriter : public sal::ZoneGroupWriter {
89 ConfigImpl* impl;
90 RGWObjVersionTracker objv;
91 std::string zonegroup_id;
92 std::string zonegroup_name;
93 public:
94 RadosZoneGroupWriter(ConfigImpl* impl, RGWObjVersionTracker objv,
95 std::string_view zonegroup_id,
96 std::string_view zonegroup_name)
97 : impl(impl), objv(std::move(objv)),
98 zonegroup_id(zonegroup_id), zonegroup_name(zonegroup_name)
99 {
100 }
101
102 int write(const DoutPrefixProvider* dpp, optional_yield y,
103 const RGWZoneGroup& info) override
104 {
105 if (zonegroup_id != info.get_id() || zonegroup_name != info.get_name()) {
106 return -EINVAL; // can't modify zonegroup id or name directly
107 }
108
109 const auto& pool = impl->zonegroup_pool;
110 const auto info_oid = zonegroup_info_oid(info.get_id());
111 return impl->write(dpp, y, pool, info_oid, Create::MustExist, info, &objv);
112 }
113
114 int rename(const DoutPrefixProvider* dpp, optional_yield y,
115 RGWZoneGroup& info, std::string_view new_name) override
116 {
117 if (zonegroup_id != info.get_id() || zonegroup_name != info.get_name()) {
118 return -EINVAL; // can't modify zonegroup id or name directly
119 }
120 if (new_name.empty()) {
121 ldpp_dout(dpp, 0) << "zonegroup cannot have an empty name" << dendl;
122 return -EINVAL;
123 }
124
125 const auto& pool = impl->zonegroup_pool;
126 const auto name = RGWNameToId{info.get_id()};
127 const auto info_oid = zonegroup_info_oid(info.get_id());
128 const auto old_oid = zonegroup_name_oid(info.get_name());
129 const auto new_oid = zonegroup_name_oid(new_name);
130
131 // link the new name
132 RGWObjVersionTracker new_objv;
133 new_objv.generate_new_write_ver(dpp->get_cct());
134 int r = impl->write(dpp, y, pool, new_oid, Create::MustNotExist,
135 name, &new_objv);
136 if (r < 0) {
137 return r;
138 }
139
140 // write the info with updated name
141 info.set_name(std::string{new_name});
142 r = impl->write(dpp, y, pool, info_oid, Create::MustExist, info, &objv);
143 if (r < 0) {
144 // on failure, unlink the new name
145 (void) impl->remove(dpp, y, pool, new_oid, &new_objv);
146 return r;
147 }
148
149 // unlink the old name
150 (void) impl->remove(dpp, y, pool, old_oid, nullptr);
151
152 zonegroup_name = new_name;
153 return 0;
154 }
155
156 int remove(const DoutPrefixProvider* dpp, optional_yield y) override
157 {
158 const auto& pool = impl->zonegroup_pool;
159 const auto info_oid = zonegroup_info_oid(zonegroup_id);
160 int r = impl->remove(dpp, y, pool, info_oid, &objv);
161 if (r < 0) {
162 return r;
163 }
164 const auto name_oid = zonegroup_name_oid(zonegroup_name);
165 (void) impl->remove(dpp, y, pool, name_oid, nullptr);
166 return 0;
167 }
168 }; // RadosZoneGroupWriter
169
170
171 int RadosConfigStore::create_zonegroup(const DoutPrefixProvider* dpp,
172 optional_yield y, bool exclusive,
173 const RGWZoneGroup& info,
174 std::unique_ptr<sal::ZoneGroupWriter>* writer)
175 {
176 if (info.get_id().empty()) {
177 ldpp_dout(dpp, 0) << "zonegroup cannot have an empty id" << dendl;
178 return -EINVAL;
179 }
180 if (info.get_name().empty()) {
181 ldpp_dout(dpp, 0) << "zonegroup cannot have an empty name" << dendl;
182 return -EINVAL;
183 }
184
185 const auto& pool = impl->zonegroup_pool;
186 const auto create = exclusive ? Create::MustNotExist : Create::MayExist;
187
188 // write the zonegroup info
189 const auto info_oid = zonegroup_info_oid(info.get_id());
190 RGWObjVersionTracker objv;
191 objv.generate_new_write_ver(dpp->get_cct());
192
193 int r = impl->write(dpp, y, pool, info_oid, create, info, &objv);
194 if (r < 0) {
195 return r;
196 }
197
198 // write the zonegroup name
199 const auto name_oid = zonegroup_name_oid(info.get_name());
200 const auto name = RGWNameToId{info.get_id()};
201 RGWObjVersionTracker name_objv;
202 name_objv.generate_new_write_ver(dpp->get_cct());
203
204 r = impl->write(dpp, y, pool, name_oid, create, name, &name_objv);
205 if (r < 0) {
206 (void) impl->remove(dpp, y, pool, info_oid, &objv);
207 return r;
208 }
209
210 if (writer) {
211 *writer = std::make_unique<RadosZoneGroupWriter>(
212 impl.get(), std::move(objv), info.get_id(), info.get_name());
213 }
214 return 0;
215 }
216
217 int RadosConfigStore::read_zonegroup_by_id(const DoutPrefixProvider* dpp,
218 optional_yield y,
219 std::string_view zonegroup_id,
220 RGWZoneGroup& info,
221 std::unique_ptr<sal::ZoneGroupWriter>* writer)
222 {
223 const auto& pool = impl->zonegroup_pool;
224 const auto info_oid = zonegroup_info_oid(zonegroup_id);
225 RGWObjVersionTracker objv;
226
227 int r = impl->read(dpp, y, pool, info_oid, info, &objv);
228 if (r < 0) {
229 return r;
230 }
231
232 if (writer) {
233 *writer = std::make_unique<RadosZoneGroupWriter>(
234 impl.get(), std::move(objv), info.get_id(), info.get_name());
235 }
236 return 0;
237 }
238
239 int RadosConfigStore::read_zonegroup_by_name(const DoutPrefixProvider* dpp,
240 optional_yield y,
241 std::string_view zonegroup_name,
242 RGWZoneGroup& info,
243 std::unique_ptr<sal::ZoneGroupWriter>* writer)
244 {
245 const auto& pool = impl->zonegroup_pool;
246
247 // look up zonegroup id by name
248 RGWNameToId name;
249 const auto name_oid = zonegroup_name_oid(zonegroup_name);
250 int r = impl->read(dpp, y, pool, name_oid, name, nullptr);
251 if (r < 0) {
252 return r;
253 }
254
255 const auto info_oid = zonegroup_info_oid(name.obj_id);
256 RGWObjVersionTracker objv;
257 r = impl->read(dpp, y, pool, info_oid, info, &objv);
258 if (r < 0) {
259 return r;
260 }
261
262 if (writer) {
263 *writer = std::make_unique<RadosZoneGroupWriter>(
264 impl.get(), std::move(objv), info.get_id(), info.get_name());
265 }
266 return 0;
267 }
268
269 int RadosConfigStore::read_default_zonegroup(const DoutPrefixProvider* dpp,
270 optional_yield y,
271 std::string_view realm_id,
272 RGWZoneGroup& info,
273 std::unique_ptr<sal::ZoneGroupWriter>* writer)
274 {
275 const auto& pool = impl->zonegroup_pool;
276
277 // read default zonegroup id
278 RGWDefaultSystemMetaObjInfo default_info;
279 const auto default_oid = default_zonegroup_oid(dpp->get_cct()->_conf, realm_id);
280 int r = impl->read(dpp, y, pool, default_oid, default_info, nullptr);
281 if (r < 0) {
282 return r;
283 }
284
285 const auto info_oid = zonegroup_info_oid(default_info.default_id);
286 RGWObjVersionTracker objv;
287 r = impl->read(dpp, y, pool, info_oid, info, &objv);
288 if (r < 0) {
289 return r;
290 }
291
292 if (writer) {
293 *writer = std::make_unique<RadosZoneGroupWriter>(
294 impl.get(), std::move(objv), info.get_id(), info.get_name());
295 }
296 return 0;
297 }
298
299 int RadosConfigStore::list_zonegroup_names(const DoutPrefixProvider* dpp,
300 optional_yield y,
301 const std::string& marker,
302 std::span<std::string> entries,
303 sal::ListResult<std::string>& result)
304 {
305 const auto& pool = impl->zonegroup_pool;
306 constexpr auto prefix = [] (std::string oid) -> std::string {
307 if (!oid.starts_with(zonegroup_names_oid_prefix)) {
308 return {};
309 }
310 return oid.substr(zonegroup_names_oid_prefix.size());
311 };
312 return impl->list(dpp, y, pool, marker, prefix, entries, result);
313 }
314
315 } // namespace rgw::rados