]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_zone.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / rgw_zone.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include <optional>
5
6 #include "common/errno.h"
7
8 #include "rgw_zone.h"
9 #include "rgw_sal_config.h"
10 #include "rgw_sync.h"
11
12 #include "services/svc_zone.h"
13
14
15 #define dout_context g_ceph_context
16 #define dout_subsys ceph_subsys_rgw
17
18 namespace rgw_zone_defaults {
19
20 static std::string default_bucket_index_pool_suffix = "rgw.buckets.index";
21 static std::string default_storage_extra_pool_suffix = "rgw.buckets.non-ec";
22 static std::string zone_info_oid_prefix = "zone_info.";
23
24 std::string zone_names_oid_prefix = "zone_names.";
25 std::string region_info_oid_prefix = "region_info.";
26 std::string zone_group_info_oid_prefix = "zonegroup_info.";
27 std::string default_region_info_oid = "default.region";
28 std::string default_zone_group_info_oid = "default.zonegroup";
29 std::string region_map_oid = "region_map";
30 std::string default_zonegroup_name = "default";
31 std::string default_zone_name = "default";
32 std::string zonegroup_names_oid_prefix = "zonegroups_names.";
33 std::string RGW_DEFAULT_ZONE_ROOT_POOL = "rgw.root";
34 std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL = "rgw.root";
35 std::string RGW_DEFAULT_PERIOD_ROOT_POOL = "rgw.root";
36 std::string avail_pools = ".pools.avail";
37 std::string default_storage_pool_suffix = "rgw.buckets.data";
38
39 }
40
41 using namespace std;
42 using namespace rgw_zone_defaults;
43
44 void encode_json_plain(const char *name, const RGWAccessKey& val, Formatter *f)
45 {
46 f->open_object_section(name);
47 val.dump_plain(f);
48 f->close_section();
49 }
50
51 static void decode_zones(map<rgw_zone_id, RGWZone>& zones, JSONObj *o)
52 {
53 RGWZone z;
54 z.decode_json(o);
55 zones[z.id] = z;
56 }
57
58 static void decode_placement_targets(map<string, RGWZoneGroupPlacementTarget>& targets, JSONObj *o)
59 {
60 RGWZoneGroupPlacementTarget t;
61 t.decode_json(o);
62 targets[t.name] = t;
63 }
64
65 void RGWZone::generate_test_instances(list<RGWZone*> &o)
66 {
67 RGWZone *z = new RGWZone;
68 o.push_back(z);
69 o.push_back(new RGWZone);
70 }
71
72 void RGWZone::dump(Formatter *f) const
73 {
74 encode_json("id", id, f);
75 encode_json("name", name, f);
76 encode_json("endpoints", endpoints, f);
77 encode_json("log_meta", log_meta, f);
78 encode_json("log_data", log_data, f);
79 encode_json("bucket_index_max_shards", bucket_index_max_shards, f);
80 encode_json("read_only", read_only, f);
81 encode_json("tier_type", tier_type, f);
82 encode_json("sync_from_all", sync_from_all, f);
83 encode_json("sync_from", sync_from, f);
84 encode_json("redirect_zone", redirect_zone, f);
85 encode_json("supported_features", supported_features, f);
86 }
87
88 void RGWZone::decode_json(JSONObj *obj)
89 {
90 JSONDecoder::decode_json("id", id, obj);
91 JSONDecoder::decode_json("name", name, obj);
92 if (id.empty()) {
93 id = name;
94 }
95 JSONDecoder::decode_json("endpoints", endpoints, obj);
96 JSONDecoder::decode_json("log_meta", log_meta, obj);
97 JSONDecoder::decode_json("log_data", log_data, obj);
98 JSONDecoder::decode_json("bucket_index_max_shards", bucket_index_max_shards, obj);
99 JSONDecoder::decode_json("read_only", read_only, obj);
100 JSONDecoder::decode_json("tier_type", tier_type, obj);
101 JSONDecoder::decode_json("sync_from_all", sync_from_all, true, obj);
102 JSONDecoder::decode_json("sync_from", sync_from, obj);
103 JSONDecoder::decode_json("redirect_zone", redirect_zone, obj);
104 JSONDecoder::decode_json("supported_features", supported_features, obj);
105 }
106
107 int RGWSystemMetaObj::init(const DoutPrefixProvider *dpp, CephContext *_cct, RGWSI_SysObj *_sysobj_svc,
108 optional_yield y,
109 bool setup_obj, bool old_format)
110 {
111 reinit_instance(_cct, _sysobj_svc);
112
113 if (!setup_obj)
114 return 0;
115
116 if (old_format && id.empty()) {
117 id = name;
118 }
119
120 if (id.empty()) {
121 id = get_predefined_id(cct);
122 }
123
124 if (id.empty()) {
125 int r;
126 if (name.empty()) {
127 name = get_predefined_name(cct);
128 }
129 if (name.empty()) {
130 r = use_default(dpp, y, old_format);
131 if (r < 0) {
132 return r;
133 }
134 } else if (!old_format) {
135 r = read_id(dpp, name, id, y);
136 if (r < 0) {
137 if (r != -ENOENT) {
138 ldpp_dout(dpp, 0) << "error in read_id for object name: " << name << " : " << cpp_strerror(-r) << dendl;
139 }
140 return r;
141 }
142 }
143 }
144
145 return read_info(dpp, id, y, old_format);
146 }
147
148 RGWZoneGroup::~RGWZoneGroup() {}
149
150 const string RGWZoneGroup::get_default_oid(bool old_region_format) const
151 {
152 if (old_region_format) {
153 if (cct->_conf->rgw_default_region_info_oid.empty()) {
154 return default_region_info_oid;
155 }
156 return cct->_conf->rgw_default_region_info_oid;
157 }
158
159 string default_oid = cct->_conf->rgw_default_zonegroup_info_oid;
160
161 if (cct->_conf->rgw_default_zonegroup_info_oid.empty()) {
162 default_oid = default_zone_group_info_oid;
163 }
164
165 default_oid += "." + realm_id;
166
167 return default_oid;
168 }
169
170 const string& RGWZoneGroup::get_info_oid_prefix(bool old_region_format) const
171 {
172 if (old_region_format) {
173 return region_info_oid_prefix;
174 }
175 return zone_group_info_oid_prefix;
176 }
177
178 const string& RGWZoneGroup::get_names_oid_prefix() const
179 {
180 return zonegroup_names_oid_prefix;
181 }
182
183 string RGWZoneGroup::get_predefined_id(CephContext *cct) const {
184 return cct->_conf.get_val<string>("rgw_zonegroup_id");
185 }
186
187 const string& RGWZoneGroup::get_predefined_name(CephContext *cct) const {
188 return cct->_conf->rgw_zonegroup;
189 }
190
191 rgw_pool RGWZoneGroup::get_pool(CephContext *cct_) const
192 {
193 if (cct_->_conf->rgw_zonegroup_root_pool.empty()) {
194 return rgw_pool(RGW_DEFAULT_ZONEGROUP_ROOT_POOL);
195 }
196
197 return rgw_pool(cct_->_conf->rgw_zonegroup_root_pool);
198 }
199
200 int RGWZoneGroup::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
201 bool old_format)
202 {
203 if (realm_id.empty()) {
204 /* try using default realm */
205 RGWRealm realm;
206 int ret = realm.init(dpp, cct, sysobj_svc, y);
207 // no default realm exist
208 if (ret < 0) {
209 return read_id(dpp, default_zonegroup_name, default_id, y);
210 }
211 realm_id = realm.get_id();
212 }
213
214 return RGWSystemMetaObj::read_default_id(dpp, default_id, y, old_format);
215 }
216
217 int RGWSystemMetaObj::use_default(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
218 {
219 return read_default_id(dpp, id, y, old_format);
220 }
221
222 void RGWSystemMetaObj::reinit_instance(CephContext *_cct, RGWSI_SysObj *_sysobj_svc)
223 {
224 cct = _cct;
225 sysobj_svc = _sysobj_svc;
226 zone_svc = _sysobj_svc->get_zone_svc();
227 }
228
229 int RGWSystemMetaObj::read_info(const DoutPrefixProvider *dpp, const string& obj_id, optional_yield y,
230 bool old_format)
231 {
232 rgw_pool pool(get_pool(cct));
233
234 bufferlist bl;
235
236 string oid = get_info_oid_prefix(old_format) + obj_id;
237
238 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj{pool, oid});
239 int ret = sysobj.rop().read(dpp, &bl, y);
240 if (ret < 0) {
241 ldpp_dout(dpp, 0) << "failed reading obj info from " << pool << ":" << oid << ": " << cpp_strerror(-ret) << dendl;
242 return ret;
243 }
244 using ceph::decode;
245
246 try {
247 auto iter = bl.cbegin();
248 decode(*this, iter);
249 } catch (buffer::error& err) {
250 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
251 return -EIO;
252 }
253
254 return 0;
255 }
256
257 void RGWZoneGroup::decode_json(JSONObj *obj)
258 {
259 RGWSystemMetaObj::decode_json(obj);
260 if (id.empty()) {
261 derr << "old format " << dendl;
262 JSONDecoder::decode_json("name", name, obj);
263 id = name;
264 }
265 JSONDecoder::decode_json("api_name", api_name, obj);
266 JSONDecoder::decode_json("is_master", is_master, obj);
267 JSONDecoder::decode_json("endpoints", endpoints, obj);
268 JSONDecoder::decode_json("hostnames", hostnames, obj);
269 JSONDecoder::decode_json("hostnames_s3website", hostnames_s3website, obj);
270 JSONDecoder::decode_json("master_zone", master_zone, obj);
271 JSONDecoder::decode_json("zones", zones, decode_zones, obj);
272 JSONDecoder::decode_json("placement_targets", placement_targets, decode_placement_targets, obj);
273 string pr;
274 JSONDecoder::decode_json("default_placement", pr, obj);
275 default_placement.from_str(pr);
276 JSONDecoder::decode_json("realm_id", realm_id, obj);
277 JSONDecoder::decode_json("sync_policy", sync_policy, obj);
278 JSONDecoder::decode_json("enabled_features", enabled_features, obj);
279 }
280
281 RGWZoneParams::~RGWZoneParams() {}
282
283 void RGWZoneParams::decode_json(JSONObj *obj)
284 {
285 RGWSystemMetaObj::decode_json(obj);
286 JSONDecoder::decode_json("domain_root", domain_root, obj);
287 JSONDecoder::decode_json("control_pool", control_pool, obj);
288 JSONDecoder::decode_json("gc_pool", gc_pool, obj);
289 JSONDecoder::decode_json("lc_pool", lc_pool, obj);
290 JSONDecoder::decode_json("log_pool", log_pool, obj);
291 JSONDecoder::decode_json("intent_log_pool", intent_log_pool, obj);
292 JSONDecoder::decode_json("roles_pool", roles_pool, obj);
293 JSONDecoder::decode_json("reshard_pool", reshard_pool, obj);
294 JSONDecoder::decode_json("usage_log_pool", usage_log_pool, obj);
295 JSONDecoder::decode_json("user_keys_pool", user_keys_pool, obj);
296 JSONDecoder::decode_json("user_email_pool", user_email_pool, obj);
297 JSONDecoder::decode_json("user_swift_pool", user_swift_pool, obj);
298 JSONDecoder::decode_json("user_uid_pool", user_uid_pool, obj);
299 JSONDecoder::decode_json("otp_pool", otp_pool, obj);
300 JSONDecoder::decode_json("system_key", system_key, obj);
301 JSONDecoder::decode_json("placement_pools", placement_pools, obj);
302 JSONDecoder::decode_json("tier_config", tier_config, obj);
303 JSONDecoder::decode_json("realm_id", realm_id, obj);
304 JSONDecoder::decode_json("notif_pool", notif_pool, obj);
305
306 }
307
308 void RGWZoneParams::dump(Formatter *f) const
309 {
310 RGWSystemMetaObj::dump(f);
311 encode_json("domain_root", domain_root, f);
312 encode_json("control_pool", control_pool, f);
313 encode_json("gc_pool", gc_pool, f);
314 encode_json("lc_pool", lc_pool, f);
315 encode_json("log_pool", log_pool, f);
316 encode_json("intent_log_pool", intent_log_pool, f);
317 encode_json("usage_log_pool", usage_log_pool, f);
318 encode_json("roles_pool", roles_pool, f);
319 encode_json("reshard_pool", reshard_pool, f);
320 encode_json("user_keys_pool", user_keys_pool, f);
321 encode_json("user_email_pool", user_email_pool, f);
322 encode_json("user_swift_pool", user_swift_pool, f);
323 encode_json("user_uid_pool", user_uid_pool, f);
324 encode_json("otp_pool", otp_pool, f);
325 encode_json_plain("system_key", system_key, f);
326 encode_json("placement_pools", placement_pools, f);
327 encode_json("tier_config", tier_config, f);
328 encode_json("realm_id", realm_id, f);
329 encode_json("notif_pool", notif_pool, f);
330 }
331
332 int RGWZoneParams::init(const DoutPrefixProvider *dpp,
333 CephContext *cct, RGWSI_SysObj *sysobj_svc,
334 optional_yield y, bool setup_obj, bool old_format)
335 {
336 if (name.empty()) {
337 name = cct->_conf->rgw_zone;
338 }
339
340 return RGWSystemMetaObj::init(dpp, cct, sysobj_svc, y, setup_obj, old_format);
341 }
342
343 rgw_pool RGWZoneParams::get_pool(CephContext *cct) const
344 {
345 if (cct->_conf->rgw_zone_root_pool.empty()) {
346 return rgw_pool(RGW_DEFAULT_ZONE_ROOT_POOL);
347 }
348
349 return rgw_pool(cct->_conf->rgw_zone_root_pool);
350 }
351
352 const string RGWZoneParams::get_default_oid(bool old_format) const
353 {
354 if (old_format) {
355 return cct->_conf->rgw_default_zone_info_oid;
356 }
357
358 return cct->_conf->rgw_default_zone_info_oid + "." + realm_id;
359 }
360
361 const string& RGWZoneParams::get_names_oid_prefix() const
362 {
363 return zone_names_oid_prefix;
364 }
365
366 const string& RGWZoneParams::get_info_oid_prefix(bool old_format) const
367 {
368 return zone_info_oid_prefix;
369 }
370
371 string RGWZoneParams::get_predefined_id(CephContext *cct) const {
372 return cct->_conf.get_val<string>("rgw_zone_id");
373 }
374
375 const string& RGWZoneParams::get_predefined_name(CephContext *cct) const {
376 return cct->_conf->rgw_zone;
377 }
378
379 int RGWZoneParams::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
380 bool old_format)
381 {
382 if (realm_id.empty()) {
383 /* try using default realm */
384 RGWRealm realm;
385 int ret = realm.init(dpp, cct, sysobj_svc, y);
386 //no default realm exist
387 if (ret < 0) {
388 return read_id(dpp, default_zone_name, default_id, y);
389 }
390 realm_id = realm.get_id();
391 }
392
393 return RGWSystemMetaObj::read_default_id(dpp, default_id, y, old_format);
394 }
395
396
397 int RGWZoneParams::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
398 {
399 if (realm_id.empty()) {
400 /* try using default realm */
401 RGWRealm realm;
402 int ret = realm.init(dpp, cct, sysobj_svc, y);
403 if (ret < 0) {
404 ldpp_dout(dpp, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
405 return -EINVAL;
406 }
407 realm_id = realm.get_id();
408 }
409
410 return RGWSystemMetaObj::set_as_default(dpp, y, exclusive);
411 }
412
413 int RGWZoneParams::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
414 {
415 /* check for old pools config */
416 rgw_raw_obj obj(domain_root, avail_pools);
417 auto sysobj = sysobj_svc->get_obj(obj);
418 int r = sysobj.rop().stat(y, dpp);
419 if (r < 0) {
420 ldpp_dout(dpp, 10) << "couldn't find old data placement pools config, setting up new ones for the zone" << dendl;
421 /* a new system, let's set new placement info */
422 RGWZonePlacementInfo default_placement;
423 default_placement.index_pool = name + "." + default_bucket_index_pool_suffix;
424 rgw_pool pool = name + "." + default_storage_pool_suffix;
425 default_placement.storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &pool, nullptr);
426 default_placement.data_extra_pool = name + "." + default_storage_extra_pool_suffix;
427 placement_pools["default-placement"] = default_placement;
428 }
429
430 r = fix_pool_names(dpp, y);
431 if (r < 0) {
432 ldpp_dout(dpp, 0) << "ERROR: fix_pool_names returned r=" << r << dendl;
433 return r;
434 }
435
436 r = RGWSystemMetaObj::create(dpp, y, exclusive);
437 if (r < 0) {
438 return r;
439 }
440
441 // try to set as default. may race with another create, so pass exclusive=true
442 // so we don't override an existing default
443 r = set_as_default(dpp, y, true);
444 if (r < 0 && r != -EEXIST) {
445 ldpp_dout(dpp, 10) << "WARNING: failed to set zone as default, r=" << r << dendl;
446 }
447
448 return 0;
449 }
450
451 rgw_pool fix_zone_pool_dup(const set<rgw_pool>& pools,
452 const string& default_prefix,
453 const string& default_suffix,
454 const rgw_pool& suggested_pool)
455 {
456 string suggested_name = suggested_pool.to_str();
457
458 string prefix = default_prefix;
459 string suffix = default_suffix;
460
461 if (!suggested_pool.empty()) {
462 prefix = suggested_name.substr(0, suggested_name.find("."));
463 suffix = suggested_name.substr(prefix.length());
464 }
465
466 rgw_pool pool(prefix + suffix);
467
468 while (pools.count(pool)) {
469 pool = prefix + "_" + std::to_string(std::rand()) + suffix;
470 }
471 return pool;
472 }
473
474 void add_zone_pools(const RGWZoneParams& info,
475 std::set<rgw_pool>& pools)
476 {
477 pools.insert(info.domain_root);
478 pools.insert(info.control_pool);
479 pools.insert(info.gc_pool);
480 pools.insert(info.log_pool);
481 pools.insert(info.intent_log_pool);
482 pools.insert(info.usage_log_pool);
483 pools.insert(info.user_keys_pool);
484 pools.insert(info.user_email_pool);
485 pools.insert(info.user_swift_pool);
486 pools.insert(info.user_uid_pool);
487 pools.insert(info.otp_pool);
488 pools.insert(info.roles_pool);
489 pools.insert(info.reshard_pool);
490 pools.insert(info.oidc_pool);
491 pools.insert(info.notif_pool);
492
493 for (const auto& [pname, placement] : info.placement_pools) {
494 pools.insert(placement.index_pool);
495 for (const auto& [sname, sc] : placement.storage_classes.get_all()) {
496 if (sc.data_pool) {
497 pools.insert(sc.data_pool.get());
498 }
499 }
500 pools.insert(placement.data_extra_pool);
501 }
502 }
503
504 namespace rgw {
505
506 int get_zones_pool_set(const DoutPrefixProvider *dpp,
507 optional_yield y,
508 rgw::sal::ConfigStore* cfgstore,
509 std::string_view my_zone_id,
510 std::set<rgw_pool>& pools)
511 {
512 std::array<std::string, 128> zone_names;
513 rgw::sal::ListResult<std::string> listing;
514 do {
515 int r = cfgstore->list_zone_names(dpp, y, listing.next,
516 zone_names, listing);
517 if (r < 0) {
518 ldpp_dout(dpp, 0) << "failed to list zones with " << cpp_strerror(r) << dendl;
519 return r;
520 }
521
522 for (const auto& name : listing.entries) {
523 RGWZoneParams info;
524 r = cfgstore->read_zone_by_name(dpp, y, name, info, nullptr);
525 if (r < 0) {
526 ldpp_dout(dpp, 0) << "failed to load zone " << name
527 << " with " << cpp_strerror(r) << dendl;
528 return r;
529 }
530 if (info.get_id() != my_zone_id) {
531 add_zone_pools(info, pools);
532 }
533 }
534 } while (!listing.next.empty());
535
536 return 0;
537 }
538
539 }
540
541 static int get_zones_pool_set(const DoutPrefixProvider *dpp,
542 CephContext* cct,
543 RGWSI_SysObj* sysobj_svc,
544 const list<string>& zone_names,
545 const string& my_zone_id,
546 set<rgw_pool>& pool_names,
547 optional_yield y)
548 {
549 for (const auto& name : zone_names) {
550 RGWZoneParams zone(name);
551 int r = zone.init(dpp, cct, sysobj_svc, y);
552 if (r < 0) {
553 ldpp_dout(dpp, 0) << "Error: failed to load zone " << name
554 << " with " << cpp_strerror(-r) << dendl;
555 return r;
556 }
557 if (zone.get_id() != my_zone_id) {
558 add_zone_pools(zone, pool_names);
559 }
560 }
561 return 0;
562 }
563
564 int RGWZoneParams::fix_pool_names(const DoutPrefixProvider *dpp, optional_yield y)
565 {
566
567 list<string> zones;
568 int r = zone_svc->list_zones(dpp, zones);
569 if (r < 0) {
570 ldpp_dout(dpp, 10) << "WARNING: driver->list_zones() returned r=" << r << dendl;
571 }
572
573 set<rgw_pool> pools;
574 r = get_zones_pool_set(dpp, cct, sysobj_svc, zones, id, pools, y);
575 if (r < 0) {
576 ldpp_dout(dpp, 0) << "Error: get_zones_pool_names" << r << dendl;
577 return r;
578 }
579
580 domain_root = fix_zone_pool_dup(pools, name, ".rgw.meta:root", domain_root);
581 control_pool = fix_zone_pool_dup(pools, name, ".rgw.control", control_pool);
582 gc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:gc", gc_pool);
583 lc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:lc", lc_pool);
584 log_pool = fix_zone_pool_dup(pools, name, ".rgw.log", log_pool);
585 intent_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:intent", intent_log_pool);
586 usage_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:usage", usage_log_pool);
587 user_keys_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.keys", user_keys_pool);
588 user_email_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.email", user_email_pool);
589 user_swift_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.swift", user_swift_pool);
590 user_uid_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.uid", user_uid_pool);
591 roles_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:roles", roles_pool);
592 reshard_pool = fix_zone_pool_dup(pools, name, ".rgw.log:reshard", reshard_pool);
593 otp_pool = fix_zone_pool_dup(pools, name, ".rgw.otp", otp_pool);
594 oidc_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:oidc", oidc_pool);
595 notif_pool = fix_zone_pool_dup(pools, name ,".rgw.log:notif", notif_pool);
596
597 for(auto& iter : placement_pools) {
598 iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix,
599 iter.second.index_pool);
600 for (auto& pi : iter.second.storage_classes.get_all()) {
601 if (pi.second.data_pool) {
602 rgw_pool& pool = pi.second.data_pool.get();
603 pool = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
604 pool);
605 }
606 }
607 iter.second.data_extra_pool= fix_zone_pool_dup(pools, name, "." + default_storage_extra_pool_suffix,
608 iter.second.data_extra_pool);
609 }
610
611 return 0;
612 }
613
614 int RGWPeriodConfig::read(const DoutPrefixProvider *dpp, RGWSI_SysObj *sysobj_svc, const std::string& realm_id,
615 optional_yield y)
616 {
617 const auto& pool = get_pool(sysobj_svc->ctx());
618 const auto& oid = get_oid(realm_id);
619 bufferlist bl;
620
621 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj{pool, oid});
622 int ret = sysobj.rop().read(dpp, &bl, y);
623 if (ret < 0) {
624 return ret;
625 }
626 using ceph::decode;
627 try {
628 auto iter = bl.cbegin();
629 decode(*this, iter);
630 } catch (buffer::error& err) {
631 return -EIO;
632 }
633 return 0;
634 }
635
636 int RGWPeriodConfig::write(const DoutPrefixProvider *dpp,
637 RGWSI_SysObj *sysobj_svc,
638 const std::string& realm_id, optional_yield y)
639 {
640 const auto& pool = get_pool(sysobj_svc->ctx());
641 const auto& oid = get_oid(realm_id);
642 bufferlist bl;
643 using ceph::encode;
644 encode(*this, bl);
645 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj{pool, oid});
646 return sysobj.wop()
647 .set_exclusive(false)
648 .write(dpp, bl, y);
649 }
650
651 void RGWPeriodConfig::decode_json(JSONObj *obj)
652 {
653 JSONDecoder::decode_json("bucket_quota", quota.bucket_quota, obj);
654 JSONDecoder::decode_json("user_quota", quota.user_quota, obj);
655 JSONDecoder::decode_json("user_ratelimit", user_ratelimit, obj);
656 JSONDecoder::decode_json("bucket_ratelimit", bucket_ratelimit, obj);
657 JSONDecoder::decode_json("anonymous_ratelimit", anon_ratelimit, obj);
658 }
659
660 void RGWPeriodConfig::dump(Formatter *f) const
661 {
662 encode_json("bucket_quota", quota.bucket_quota, f);
663 encode_json("user_quota", quota.user_quota, f);
664 encode_json("user_ratelimit", user_ratelimit, f);
665 encode_json("bucket_ratelimit", bucket_ratelimit, f);
666 encode_json("anonymous_ratelimit", anon_ratelimit, f);
667 }
668
669 std::string RGWPeriodConfig::get_oid(const std::string& realm_id)
670 {
671 if (realm_id.empty()) {
672 return "period_config.default";
673 }
674 return "period_config." + realm_id;
675 }
676
677 rgw_pool RGWPeriodConfig::get_pool(CephContext *cct)
678 {
679 const auto& pool_name = cct->_conf->rgw_period_root_pool;
680 if (pool_name.empty()) {
681 return {RGW_DEFAULT_PERIOD_ROOT_POOL};
682 }
683 return {pool_name};
684 }
685
686 int RGWSystemMetaObj::delete_obj(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
687 {
688 rgw_pool pool(get_pool(cct));
689
690 /* check to see if obj is the default */
691 RGWDefaultSystemMetaObjInfo default_info;
692 int ret = read_default(dpp, default_info, get_default_oid(old_format), y);
693 if (ret < 0 && ret != -ENOENT)
694 return ret;
695 if (default_info.default_id == id || (old_format && default_info.default_id == name)) {
696 string oid = get_default_oid(old_format);
697 rgw_raw_obj default_named_obj(pool, oid);
698 auto sysobj = sysobj_svc->get_obj(default_named_obj);
699 ret = sysobj.wop().remove(dpp, y);
700 if (ret < 0) {
701 ldpp_dout(dpp, 0) << "Error delete default obj name " << name << ": " << cpp_strerror(-ret) << dendl;
702 return ret;
703 }
704 }
705 if (!old_format) {
706 string oid = get_names_oid_prefix() + name;
707 rgw_raw_obj object_name(pool, oid);
708 auto sysobj = sysobj_svc->get_obj(object_name);
709 ret = sysobj.wop().remove(dpp, y);
710 if (ret < 0) {
711 ldpp_dout(dpp, 0) << "Error delete obj name " << name << ": " << cpp_strerror(-ret) << dendl;
712 return ret;
713 }
714 }
715
716 string oid = get_info_oid_prefix(old_format);
717 if (old_format) {
718 oid += name;
719 } else {
720 oid += id;
721 }
722
723 rgw_raw_obj object_id(pool, oid);
724 auto sysobj = sysobj_svc->get_obj(object_id);
725 ret = sysobj.wop().remove(dpp, y);
726 if (ret < 0) {
727 ldpp_dout(dpp, 0) << "Error delete object id " << id << ": " << cpp_strerror(-ret) << dendl;
728 }
729
730 return ret;
731 }
732
733 void RGWZoneGroup::dump(Formatter *f) const
734 {
735 RGWSystemMetaObj::dump(f);
736 encode_json("api_name", api_name, f);
737 encode_json("is_master", is_master, f);
738 encode_json("endpoints", endpoints, f);
739 encode_json("hostnames", hostnames, f);
740 encode_json("hostnames_s3website", hostnames_s3website, f);
741 encode_json("master_zone", master_zone, f);
742 encode_json_map("zones", zones, f); /* more friendly representation */
743 encode_json_map("placement_targets", placement_targets, f); /* more friendly representation */
744 encode_json("default_placement", default_placement, f);
745 encode_json("realm_id", realm_id, f);
746 encode_json("sync_policy", sync_policy, f);
747 encode_json("enabled_features", enabled_features, f);
748 }
749
750 void RGWZoneGroupPlacementTarget::decode_json(JSONObj *obj)
751 {
752 JSONDecoder::decode_json("name", name, obj);
753 JSONDecoder::decode_json("tags", tags, obj);
754 JSONDecoder::decode_json("storage_classes", storage_classes, obj);
755 if (storage_classes.empty()) {
756 storage_classes.insert(RGW_STORAGE_CLASS_STANDARD);
757 }
758 JSONDecoder::decode_json("tier_targets", tier_targets, obj);
759 }
760
761 void RGWZonePlacementInfo::dump(Formatter *f) const
762 {
763 encode_json("index_pool", index_pool, f);
764 encode_json("storage_classes", storage_classes, f);
765 encode_json("data_extra_pool", data_extra_pool, f);
766 encode_json("index_type", (uint32_t)index_type, f);
767 encode_json("inline_data", inline_data, f);
768
769 /* no real need for backward compatibility of compression_type and data_pool in here,
770 * rather not clutter the output */
771 }
772
773 void RGWZonePlacementInfo::decode_json(JSONObj *obj)
774 {
775 JSONDecoder::decode_json("index_pool", index_pool, obj);
776 JSONDecoder::decode_json("storage_classes", storage_classes, obj);
777 JSONDecoder::decode_json("data_extra_pool", data_extra_pool, obj);
778 uint32_t it;
779 JSONDecoder::decode_json("index_type", it, obj);
780 JSONDecoder::decode_json("inline_data", inline_data, obj);
781 index_type = (rgw::BucketIndexType)it;
782
783 /* backward compatibility, these are now defined in storage_classes */
784 string standard_compression_type;
785 string *pcompression = nullptr;
786 if (JSONDecoder::decode_json("compression", standard_compression_type, obj)) {
787 pcompression = &standard_compression_type;
788 }
789 rgw_pool standard_data_pool;
790 rgw_pool *ppool = nullptr;
791 if (JSONDecoder::decode_json("data_pool", standard_data_pool, obj)) {
792 ppool = &standard_data_pool;
793 }
794 if (ppool || pcompression) {
795 storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, ppool, pcompression);
796 }
797 }
798
799 void RGWSystemMetaObj::dump(Formatter *f) const
800 {
801 encode_json("id", id , f);
802 encode_json("name", name , f);
803 }
804
805 void RGWSystemMetaObj::decode_json(JSONObj *obj)
806 {
807 JSONDecoder::decode_json("id", id, obj);
808 JSONDecoder::decode_json("name", name, obj);
809 }
810
811 int RGWSystemMetaObj::read_default(const DoutPrefixProvider *dpp,
812 RGWDefaultSystemMetaObjInfo& default_info,
813 const string& oid, optional_yield y)
814 {
815 using ceph::decode;
816 auto pool = get_pool(cct);
817 bufferlist bl;
818
819 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj(pool, oid));
820 int ret = sysobj.rop().read(dpp, &bl, y);
821 if (ret < 0)
822 return ret;
823
824 try {
825 auto iter = bl.cbegin();
826 decode(default_info, iter);
827 } catch (buffer::error& err) {
828 ldpp_dout(dpp, 0) << "error decoding data from " << pool << ":" << oid << dendl;
829 return -EIO;
830 }
831
832 return 0;
833 }
834
835 void RGWZoneGroupPlacementTarget::dump(Formatter *f) const
836 {
837 encode_json("name", name, f);
838 encode_json("tags", tags, f);
839 encode_json("storage_classes", storage_classes, f);
840 if (!tier_targets.empty()) {
841 encode_json("tier_targets", tier_targets, f);
842 }
843 }
844
845 void RGWZoneGroupPlacementTier::decode_json(JSONObj *obj)
846 {
847 JSONDecoder::decode_json("tier_type", tier_type, obj);
848 JSONDecoder::decode_json("storage_class", storage_class, obj);
849 JSONDecoder::decode_json("retain_head_object", retain_head_object, obj);
850
851 if (tier_type == "cloud-s3") {
852 JSONDecoder::decode_json("s3", t.s3, obj);
853 }
854 }
855
856 void RGWZoneStorageClasses::dump(Formatter *f) const
857 {
858 for (auto& i : m) {
859 encode_json(i.first.c_str(), i.second, f);
860 }
861 }
862
863 void RGWZoneStorageClasses::decode_json(JSONObj *obj)
864 {
865 JSONFormattable f;
866 decode_json_obj(f, obj);
867
868 for (auto& field : f.object()) {
869 JSONObj *field_obj = obj->find_obj(field.first);
870 assert(field_obj);
871
872 decode_json_obj(m[field.first], field_obj);
873 }
874 standard_class = &m[RGW_STORAGE_CLASS_STANDARD];
875 }
876
877 void RGWZoneGroupPlacementTier::dump(Formatter *f) const
878 {
879 encode_json("tier_type", tier_type, f);
880 encode_json("storage_class", storage_class, f);
881 encode_json("retain_head_object", retain_head_object, f);
882
883 if (tier_type == "cloud-s3") {
884 encode_json("s3", t.s3, f);
885 }
886 }
887
888 void RGWZoneGroupPlacementTierS3::decode_json(JSONObj *obj)
889 {
890 JSONDecoder::decode_json("endpoint", endpoint, obj);
891 JSONDecoder::decode_json("access_key", key.id, obj);
892 JSONDecoder::decode_json("secret", key.key, obj);
893 JSONDecoder::decode_json("region", region, obj);
894 string s;
895 JSONDecoder::decode_json("host_style", s, obj);
896 if (s != "virtual") {
897 host_style = PathStyle;
898 } else {
899 host_style = VirtualStyle;
900 }
901 JSONDecoder::decode_json("target_storage_class", target_storage_class, obj);
902 JSONDecoder::decode_json("target_path", target_path, obj);
903 JSONDecoder::decode_json("acl_mappings", acl_mappings, obj);
904 JSONDecoder::decode_json("multipart_sync_threshold", multipart_sync_threshold, obj);
905 JSONDecoder::decode_json("multipart_min_part_size", multipart_min_part_size, obj);
906 }
907
908 void RGWZoneStorageClass::dump(Formatter *f) const
909 {
910 if (data_pool) {
911 encode_json("data_pool", data_pool.get(), f);
912 }
913 if (compression_type) {
914 encode_json("compression_type", compression_type.get(), f);
915 }
916 }
917
918 void RGWZoneStorageClass::decode_json(JSONObj *obj)
919 {
920 JSONDecoder::decode_json("data_pool", data_pool, obj);
921 JSONDecoder::decode_json("compression_type", compression_type, obj);
922 }
923
924 void RGWTierACLMapping::decode_json(JSONObj *obj)
925 {
926 string s;
927 JSONDecoder::decode_json("type", s, obj);
928 if (s == "email") {
929 type = ACL_TYPE_EMAIL_USER;
930 } else if (s == "uri") {
931 type = ACL_TYPE_GROUP;
932 } else {
933 type = ACL_TYPE_CANON_USER;
934 }
935
936 JSONDecoder::decode_json("source_id", source_id, obj);
937 JSONDecoder::decode_json("dest_id", dest_id, obj);
938 }
939
940 void RGWZoneGroupPlacementTierS3::dump(Formatter *f) const
941 {
942 encode_json("endpoint", endpoint, f);
943 encode_json("access_key", key.id, f);
944 encode_json("secret", key.key, f);
945 encode_json("region", region, f);
946 string s = (host_style == PathStyle ? "path" : "virtual");
947 encode_json("host_style", s, f);
948 encode_json("target_storage_class", target_storage_class, f);
949 encode_json("target_path", target_path, f);
950 encode_json("acl_mappings", acl_mappings, f);
951 encode_json("multipart_sync_threshold", multipart_sync_threshold, f);
952 encode_json("multipart_min_part_size", multipart_min_part_size, f);
953 }
954
955 void RGWTierACLMapping::dump(Formatter *f) const
956 {
957 string s;
958 switch (type) {
959 case ACL_TYPE_EMAIL_USER:
960 s = "email";
961 break;
962 case ACL_TYPE_GROUP:
963 s = "uri";
964 break;
965 default:
966 s = "id";
967 break;
968 }
969 encode_json("type", s, f);
970 encode_json("source_id", source_id, f);
971 encode_json("dest_id", dest_id, f);
972 }
973
974 void RGWPeriodMap::dump(Formatter *f) const
975 {
976 encode_json("id", id, f);
977 encode_json_map("zonegroups", zonegroups, f);
978 encode_json("short_zone_ids", short_zone_ids, f);
979 }
980
981 static void decode_zonegroups(map<string, RGWZoneGroup>& zonegroups, JSONObj *o)
982 {
983 RGWZoneGroup zg;
984 zg.decode_json(o);
985 zonegroups[zg.get_id()] = zg;
986 }
987
988 void RGWPeriodMap::decode_json(JSONObj *obj)
989 {
990 JSONDecoder::decode_json("id", id, obj);
991 JSONDecoder::decode_json("zonegroups", zonegroups, decode_zonegroups, obj);
992 /* backward compatability with region */
993 if (zonegroups.empty()) {
994 JSONDecoder::decode_json("regions", zonegroups, obj);
995 }
996 /* backward compatability with region */
997 if (master_zonegroup.empty()) {
998 JSONDecoder::decode_json("master_region", master_zonegroup, obj);
999 }
1000 JSONDecoder::decode_json("short_zone_ids", short_zone_ids, obj);
1001 }
1002
1003 void RGWPeriodMap::decode(bufferlist::const_iterator& bl) {
1004 DECODE_START(2, bl);
1005 decode(id, bl);
1006 decode(zonegroups, bl);
1007 decode(master_zonegroup, bl);
1008 if (struct_v >= 2) {
1009 decode(short_zone_ids, bl);
1010 }
1011 DECODE_FINISH(bl);
1012
1013 zonegroups_by_api.clear();
1014 for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
1015 iter != zonegroups.end(); ++iter) {
1016 RGWZoneGroup& zonegroup = iter->second;
1017 zonegroups_by_api[zonegroup.api_name] = zonegroup;
1018 if (zonegroup.is_master_zonegroup()) {
1019 master_zonegroup = zonegroup.get_id();
1020 }
1021 }
1022 }
1023
1024 void RGWPeriodMap::encode(bufferlist& bl) const
1025 {
1026 ENCODE_START(2, 1, bl);
1027 encode(id, bl);
1028 encode(zonegroups, bl);
1029 encode(master_zonegroup, bl);
1030 encode(short_zone_ids, bl);
1031 ENCODE_FINISH(bl);
1032 }
1033
1034 int RGWSystemMetaObj::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
1035 {
1036 int ret;
1037
1038 /* check to see the name is not used */
1039 ret = read_id(dpp, name, id, y);
1040 if (exclusive && ret == 0) {
1041 ldpp_dout(dpp, 10) << "ERROR: name " << name << " already in use for obj id " << id << dendl;
1042 return -EEXIST;
1043 } else if ( ret < 0 && ret != -ENOENT) {
1044 ldpp_dout(dpp, 0) << "failed reading obj id " << id << ": " << cpp_strerror(-ret) << dendl;
1045 return ret;
1046 }
1047
1048 if (id.empty()) {
1049 /* create unique id */
1050 uuid_d new_uuid;
1051 char uuid_str[37];
1052 new_uuid.generate_random();
1053 new_uuid.print(uuid_str);
1054 id = uuid_str;
1055 }
1056
1057 ret = store_info(dpp, exclusive, y);
1058 if (ret < 0) {
1059 ldpp_dout(dpp, 0) << "ERROR: storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
1060 return ret;
1061 }
1062
1063 return store_name(dpp, exclusive, y);
1064 }
1065
1066 int RGWSystemMetaObj::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
1067 bool old_format)
1068 {
1069 RGWDefaultSystemMetaObjInfo default_info;
1070
1071 int ret = read_default(dpp, default_info, get_default_oid(old_format), y);
1072 if (ret < 0) {
1073 return ret;
1074 }
1075
1076 default_id = default_info.default_id;
1077
1078 return 0;
1079 }
1080
1081 int RGWSystemMetaObj::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
1082 {
1083 using ceph::encode;
1084 string oid = get_default_oid();
1085
1086 rgw_pool pool(get_pool(cct));
1087 bufferlist bl;
1088
1089 RGWDefaultSystemMetaObjInfo default_info;
1090 default_info.default_id = id;
1091
1092 encode(default_info, bl);
1093
1094 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj(pool, oid));
1095 int ret = sysobj.wop()
1096 .set_exclusive(exclusive)
1097 .write(dpp, bl, y);
1098 if (ret < 0)
1099 return ret;
1100
1101 return 0;
1102 }
1103
1104 int RGWSystemMetaObj::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
1105 {
1106 rgw_pool pool(get_pool(cct));
1107
1108 string oid = get_info_oid_prefix() + id;
1109
1110 bufferlist bl;
1111 using ceph::encode;
1112 encode(*this, bl);
1113 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj{pool, oid});
1114 return sysobj.wop()
1115 .set_exclusive(exclusive)
1116 .write(dpp, bl, y);
1117 }
1118
1119 int RGWSystemMetaObj::read_id(const DoutPrefixProvider *dpp, const string& obj_name, string& object_id,
1120 optional_yield y)
1121 {
1122 using ceph::decode;
1123 rgw_pool pool(get_pool(cct));
1124 bufferlist bl;
1125
1126 string oid = get_names_oid_prefix() + obj_name;
1127
1128 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj(pool, oid));
1129 int ret = sysobj.rop().read(dpp, &bl, y);
1130 if (ret < 0) {
1131 return ret;
1132 }
1133
1134 RGWNameToId nameToId;
1135 try {
1136 auto iter = bl.cbegin();
1137 decode(nameToId, iter);
1138 } catch (buffer::error& err) {
1139 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
1140 return -EIO;
1141 }
1142 object_id = nameToId.obj_id;
1143 return 0;
1144 }
1145
1146 int RGWSystemMetaObj::store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
1147 {
1148 rgw_pool pool(get_pool(cct));
1149 string oid = get_names_oid_prefix() + name;
1150
1151 RGWNameToId nameToId;
1152 nameToId.obj_id = id;
1153
1154 bufferlist bl;
1155 using ceph::encode;
1156 encode(nameToId, bl);
1157 auto sysobj = sysobj_svc->get_obj(rgw_raw_obj(pool, oid));
1158 return sysobj.wop()
1159 .set_exclusive(exclusive)
1160 .write(dpp, bl, y);
1161 }
1162
1163 bool RGWPeriodMap::find_zone_by_id(const rgw_zone_id& zone_id,
1164 RGWZoneGroup *zonegroup,
1165 RGWZone *zone) const
1166 {
1167 for (auto& iter : zonegroups) {
1168 auto& zg = iter.second;
1169
1170 auto ziter = zg.zones.find(zone_id);
1171 if (ziter != zg.zones.end()) {
1172 *zonegroup = zg;
1173 *zone = ziter->second;
1174 return true;
1175 }
1176 }
1177
1178 return false;
1179 }
1180
1181 int RGWZoneGroup::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
1182 {
1183 if (realm_id.empty()) {
1184 /* try using default realm */
1185 RGWRealm realm;
1186 int ret = realm.init(dpp, cct, sysobj_svc, y);
1187 if (ret < 0) {
1188 ldpp_dout(dpp, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
1189 return -EINVAL;
1190 }
1191 realm_id = realm.get_id();
1192 }
1193
1194 return RGWSystemMetaObj::set_as_default(dpp, y, exclusive);
1195 }
1196
1197 int RGWSystemMetaObj::write(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
1198 {
1199 int ret = store_info(dpp, exclusive, y);
1200 if (ret < 0) {
1201 ldpp_dout(dpp, 20) << __func__ << "(): store_info() returned ret=" << ret << dendl;
1202 return ret;
1203 }
1204 ret = store_name(dpp, exclusive, y);
1205 if (ret < 0) {
1206 ldpp_dout(dpp, 20) << __func__ << "(): store_name() returned ret=" << ret << dendl;
1207 return ret;
1208 }
1209 return 0;
1210 }
1211
1212 namespace rgw {
1213
1214 int init_zone_pool_names(const DoutPrefixProvider *dpp, optional_yield y,
1215 const std::set<rgw_pool>& pools, RGWZoneParams& info)
1216 {
1217 info.domain_root = fix_zone_pool_dup(pools, info.name, ".rgw.meta:root", info.domain_root);
1218 info.control_pool = fix_zone_pool_dup(pools, info.name, ".rgw.control", info.control_pool);
1219 info.gc_pool = fix_zone_pool_dup(pools, info.name, ".rgw.log:gc", info.gc_pool);
1220 info.lc_pool = fix_zone_pool_dup(pools, info.name, ".rgw.log:lc", info.lc_pool);
1221 info.log_pool = fix_zone_pool_dup(pools, info.name, ".rgw.log", info.log_pool);
1222 info.intent_log_pool = fix_zone_pool_dup(pools, info.name, ".rgw.log:intent", info.intent_log_pool);
1223 info.usage_log_pool = fix_zone_pool_dup(pools, info.name, ".rgw.log:usage", info.usage_log_pool);
1224 info.user_keys_pool = fix_zone_pool_dup(pools, info.name, ".rgw.meta:users.keys", info.user_keys_pool);
1225 info.user_email_pool = fix_zone_pool_dup(pools, info.name, ".rgw.meta:users.email", info.user_email_pool);
1226 info.user_swift_pool = fix_zone_pool_dup(pools, info.name, ".rgw.meta:users.swift", info.user_swift_pool);
1227 info.user_uid_pool = fix_zone_pool_dup(pools, info.name, ".rgw.meta:users.uid", info.user_uid_pool);
1228 info.roles_pool = fix_zone_pool_dup(pools, info.name, ".rgw.meta:roles", info.roles_pool);
1229 info.reshard_pool = fix_zone_pool_dup(pools, info.name, ".rgw.log:reshard", info.reshard_pool);
1230 info.otp_pool = fix_zone_pool_dup(pools, info.name, ".rgw.otp", info.otp_pool);
1231 info.oidc_pool = fix_zone_pool_dup(pools, info.name, ".rgw.meta:oidc", info.oidc_pool);
1232 info.notif_pool = fix_zone_pool_dup(pools, info.name, ".rgw.log:notif", info.notif_pool);
1233
1234 for (auto& [pname, placement] : info.placement_pools) {
1235 placement.index_pool = fix_zone_pool_dup(pools, info.name, "." + default_bucket_index_pool_suffix, placement.index_pool);
1236 placement.data_extra_pool= fix_zone_pool_dup(pools, info.name, "." + default_storage_extra_pool_suffix, placement.data_extra_pool);
1237 for (auto& [sname, sc] : placement.storage_classes.get_all()) {
1238 if (sc.data_pool) {
1239 sc.data_pool = fix_zone_pool_dup(pools, info.name, "." + default_storage_pool_suffix, *sc.data_pool);
1240 }
1241 }
1242 }
1243
1244 return 0;
1245 }
1246
1247 int add_zone_to_group(const DoutPrefixProvider* dpp, RGWZoneGroup& zonegroup,
1248 const RGWZoneParams& zone_params,
1249 const bool *pis_master, const bool *pread_only,
1250 const std::list<std::string>& endpoints,
1251 const std::string *ptier_type,
1252 const bool *psync_from_all,
1253 const std::list<std::string>& sync_from,
1254 const std::list<std::string>& sync_from_rm,
1255 const std::string *predirect_zone,
1256 std::optional<int> bucket_index_max_shards,
1257 const rgw::zone_features::set& enable_features,
1258 const rgw::zone_features::set& disable_features)
1259 {
1260 const std::string& zone_id = zone_params.id;
1261 const std::string& zone_name = zone_params.name;
1262
1263 if (zone_id.empty()) {
1264 ldpp_dout(dpp, -1) << __func__ << " requires a zone id" << dendl;
1265 return -EINVAL;
1266 }
1267 if (zone_name.empty()) {
1268 ldpp_dout(dpp, -1) << __func__ << " requires a zone name" << dendl;
1269 return -EINVAL;
1270 }
1271
1272 // check for duplicate zone name on insert
1273 if (!zonegroup.zones.count(zone_id)) {
1274 for (const auto& [id, zone] : zonegroup.zones) {
1275 if (zone.name == zone_name) {
1276 ldpp_dout(dpp, 0) << "ERROR: found existing zone name " << zone_name
1277 << " (" << id << ") in zonegroup " << zonegroup.name << dendl;
1278 return -EEXIST;
1279 }
1280 }
1281 }
1282
1283 rgw_zone_id& master_zone = zonegroup.master_zone;
1284 if (pis_master) {
1285 if (*pis_master) {
1286 if (!master_zone.empty() && master_zone != zone_id) {
1287 ldpp_dout(dpp, 0) << "NOTICE: overriding master zone: "
1288 << master_zone << dendl;
1289 }
1290 master_zone = zone_id;
1291 } else if (master_zone == zone_id) {
1292 master_zone.clear();
1293 }
1294 } else if (master_zone.empty() && zonegroup.zones.empty()) {
1295 ldpp_dout(dpp, 0) << "NOTICE: promoted " << zone_name
1296 << " as new master_zone of zonegroup " << zonegroup.name << dendl;
1297 master_zone = zone_id;
1298 }
1299
1300 // make sure the zone's placement targets are named in the zonegroup
1301 for (const auto& [name, placement] : zone_params.placement_pools) {
1302 auto target = RGWZoneGroupPlacementTarget{.name = name};
1303 zonegroup.placement_targets.emplace(name, std::move(target));
1304 }
1305
1306 RGWZone& zone = zonegroup.zones[zone_params.id];
1307 zone.id = zone_params.id;
1308 zone.name = zone_params.name;
1309 if (!endpoints.empty()) {
1310 zone.endpoints = endpoints;
1311 }
1312 if (pread_only) {
1313 zone.read_only = *pread_only;
1314 }
1315 if (ptier_type) {
1316 zone.tier_type = *ptier_type;
1317 }
1318 if (psync_from_all) {
1319 zone.sync_from_all = *psync_from_all;
1320 }
1321 if (predirect_zone) {
1322 zone.redirect_zone = *predirect_zone;
1323 }
1324 if (bucket_index_max_shards) {
1325 zone.bucket_index_max_shards = *bucket_index_max_shards;
1326 }
1327
1328 // add/remove sync_from
1329 for (auto add : sync_from) {
1330 zone.sync_from.insert(add);
1331 }
1332
1333 for (const auto& rm : sync_from_rm) {
1334 auto i = zone.sync_from.find(rm);
1335 if (i == zone.sync_from.end()) {
1336 ldpp_dout(dpp, 1) << "WARNING: zone \"" << rm
1337 << "\" was not in sync_from" << dendl;
1338 continue;
1339 }
1340 zone.sync_from.erase(i);
1341 }
1342
1343 // add/remove supported features
1344 zone.supported_features.insert(enable_features.begin(),
1345 enable_features.end());
1346
1347 for (const auto& feature : disable_features) {
1348 if (zonegroup.enabled_features.contains(feature)) {
1349 ldpp_dout(dpp, -1) << "ERROR: Cannot disable zone feature \"" << feature
1350 << "\" until it's been disabled in zonegroup " << zonegroup.name << dendl;
1351 return -EINVAL;
1352 }
1353 auto i = zone.supported_features.find(feature);
1354 if (i == zone.supported_features.end()) {
1355 ldpp_dout(dpp, 1) << "WARNING: zone feature \"" << feature
1356 << "\" was not enabled in zone " << zone.name << dendl;
1357 continue;
1358 }
1359 zone.supported_features.erase(i);
1360 }
1361
1362 const bool log_data = zonegroup.zones.size() > 1;
1363 for (auto& [id, zone] : zonegroup.zones) {
1364 zone.log_data = log_data;
1365 }
1366
1367 return 0;
1368 }
1369
1370 } // namespace rgw
1371