]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_zone.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / rgw / rgw_zone.cc
CommitLineData
11fdf7f2 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
11fdf7f2
TL
3
4#include "common/errno.h"
5
6#include "rgw_zone.h"
7#include "rgw_realm_watcher.h"
8#include "rgw_meta_sync_status.h"
9#include "rgw_sync.h"
10
11#include "services/svc_zone.h"
12#include "services/svc_sys_obj.h"
13
20effc67
TL
14#include "common/ceph_json.h"
15#include "common/Formatter.h"
16
17#define dout_context g_ceph_context
11fdf7f2
TL
18#define dout_subsys ceph_subsys_rgw
19
20namespace rgw_zone_defaults {
21
22std::string zone_info_oid_prefix = "zone_info.";
23std::string zone_names_oid_prefix = "zone_names.";
24std::string region_info_oid_prefix = "region_info.";
25std::string realm_names_oid_prefix = "realms_names.";
26std::string zone_group_info_oid_prefix = "zonegroup_info.";
27std::string realm_info_oid_prefix = "realms.";
28std::string default_region_info_oid = "default.region";
29std::string default_zone_group_info_oid = "default.zonegroup";
30std::string period_info_oid_prefix = "periods.";
31std::string period_latest_epoch_info_oid = ".latest_epoch";
32std::string region_map_oid = "region_map";
33std::string default_realm_info_oid = "default.realm";
34std::string default_zonegroup_name = "default";
35std::string default_zone_name = "default";
36std::string zonegroup_names_oid_prefix = "zonegroups_names.";
37std::string RGW_DEFAULT_ZONE_ROOT_POOL = "rgw.root";
38std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL = "rgw.root";
39std::string RGW_DEFAULT_REALM_ROOT_POOL = "rgw.root";
40std::string RGW_DEFAULT_PERIOD_ROOT_POOL = "rgw.root";
41std::string default_bucket_index_pool_suffix = "rgw.buckets.index";
42std::string default_storage_extra_pool_suffix = "rgw.buckets.non-ec";
43std::string avail_pools = ".pools.avail";
44std::string default_storage_pool_suffix = "rgw.buckets.data";
45
46}
47
20effc67 48using namespace std;
11fdf7f2
TL
49using namespace rgw_zone_defaults;
50
20effc67
TL
51RGWMetaSyncStatusManager::~RGWMetaSyncStatusManager(){}
52
11fdf7f2
TL
53#define FIRST_EPOCH 1
54
20effc67
TL
55struct RGWAccessKey;
56
57void encode_json_plain(const char *name, const RGWAccessKey& val, Formatter *f)
58{
59 f->open_object_section(name);
60 val.dump_plain(f);
61 f->close_section();
62}
63
11fdf7f2
TL
64void RGWDefaultZoneGroupInfo::dump(Formatter *f) const {
65 encode_json("default_zonegroup", default_zonegroup, f);
66}
67
68void RGWDefaultZoneGroupInfo::decode_json(JSONObj *obj) {
69
70 JSONDecoder::decode_json("default_zonegroup", default_zonegroup, obj);
71 /* backward compatability with region */
72 if (default_zonegroup.empty()) {
73 JSONDecoder::decode_json("default_region", default_zonegroup, obj);
74 }
75}
76
77rgw_pool RGWZoneGroup::get_pool(CephContext *cct_) const
78{
79 if (cct_->_conf->rgw_zonegroup_root_pool.empty()) {
80 return rgw_pool(RGW_DEFAULT_ZONEGROUP_ROOT_POOL);
81 }
82
83 return rgw_pool(cct_->_conf->rgw_zonegroup_root_pool);
84}
85
b3b6e05e 86int RGWZoneGroup::create_default(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2
TL
87{
88 name = default_zonegroup_name;
89 api_name = default_zonegroup_name;
90 is_master = true;
91
92 RGWZoneGroupPlacementTarget placement_target;
93 placement_target.name = "default-placement";
94 placement_targets[placement_target.name] = placement_target;
95 default_placement.name = "default-placement";
96
97 RGWZoneParams zone_params(default_zone_name);
98
b3b6e05e 99 int r = zone_params.init(dpp, cct, sysobj_svc, y, false);
11fdf7f2 100 if (r < 0) {
b3b6e05e 101 ldpp_dout(dpp, 0) << "create_default: error initializing zone params: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
102 return r;
103 }
104
b3b6e05e 105 r = zone_params.create_default(dpp, y);
11fdf7f2 106 if (r < 0 && r != -EEXIST) {
b3b6e05e 107 ldpp_dout(dpp, 0) << "create_default: error in create_default zone params: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
108 return r;
109 } else if (r == -EEXIST) {
b3b6e05e 110 ldpp_dout(dpp, 10) << "zone_params::create_default() returned -EEXIST, we raced with another default zone_params creation" << dendl;
11fdf7f2 111 zone_params.clear_id();
b3b6e05e 112 r = zone_params.init(dpp, cct, sysobj_svc, y);
11fdf7f2 113 if (r < 0) {
b3b6e05e 114 ldpp_dout(dpp, 0) << "create_default: error in init existing zone params: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
115 return r;
116 }
b3b6e05e 117 ldpp_dout(dpp, 20) << "zone_params::create_default() " << zone_params.get_name() << " id " << zone_params.get_id()
11fdf7f2
TL
118 << dendl;
119 }
120
121 RGWZone& default_zone = zones[zone_params.get_id()];
122 default_zone.name = zone_params.get_name();
123 default_zone.id = zone_params.get_id();
124 master_zone = default_zone.id;
125
b3b6e05e 126 r = create(dpp, y);
11fdf7f2 127 if (r < 0 && r != -EEXIST) {
b3b6e05e 128 ldpp_dout(dpp, 0) << "error storing zone group info: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
129 return r;
130 }
131
132 if (r == -EEXIST) {
b3b6e05e 133 ldpp_dout(dpp, 10) << "create_default() returned -EEXIST, we raced with another zonegroup creation" << dendl;
11fdf7f2 134 id.clear();
b3b6e05e 135 r = init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
136 if (r < 0) {
137 return r;
138 }
139 }
140
141 if (old_format) {
142 name = id;
143 }
144
b3b6e05e 145 post_process_params(dpp, y);
11fdf7f2
TL
146
147 return 0;
148}
149
150const 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
170const 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
178const string& RGWZoneGroup::get_names_oid_prefix() const
179{
180 return zonegroup_names_oid_prefix;
181}
182
20effc67
TL
183string RGWZoneGroup::get_predefined_id(CephContext *cct) const {
184 return cct->_conf.get_val<string>("rgw_zonegroup_id");
185}
186
11fdf7f2
TL
187const string& RGWZoneGroup::get_predefined_name(CephContext *cct) const {
188 return cct->_conf->rgw_zonegroup;
189}
190
191int RGWZoneGroup::equals(const string& other_zonegroup) const
192{
193 if (is_master && other_zonegroup.empty())
194 return true;
195
196 return (id == other_zonegroup);
197}
198
b3b6e05e
TL
199int RGWZoneGroup::add_zone(const DoutPrefixProvider *dpp,
200 const RGWZoneParams& zone_params, bool *is_master, bool *read_only,
11fdf7f2
TL
201 const list<string>& endpoints, const string *ptier_type,
202 bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm,
9f95a23c 203 string *predirect_zone, std::optional<int> bucket_index_max_shards,
f67539c2
TL
204 RGWSyncModulesManager *sync_mgr,
205 optional_yield y)
11fdf7f2
TL
206{
207 auto& zone_id = zone_params.get_id();
208 auto& zone_name = zone_params.get_name();
209
210 // check for duplicate zone name on insert
211 if (!zones.count(zone_id)) {
212 for (const auto& zone : zones) {
213 if (zone.second.name == zone_name) {
b3b6e05e 214 ldpp_dout(dpp, 0) << "ERROR: found existing zone name " << zone_name
11fdf7f2
TL
215 << " (" << zone.first << ") in zonegroup " << get_name() << dendl;
216 return -EEXIST;
217 }
218 }
219 }
220
221 if (is_master) {
222 if (*is_master) {
223 if (!master_zone.empty() && master_zone != zone_id) {
b3b6e05e 224 ldpp_dout(dpp, 0) << "NOTICE: overriding master zone: " << master_zone << dendl;
11fdf7f2
TL
225 }
226 master_zone = zone_id;
227 } else if (master_zone == zone_id) {
228 master_zone.clear();
229 }
230 }
231
232 RGWZone& zone = zones[zone_id];
233 zone.name = zone_name;
234 zone.id = zone_id;
235 if (!endpoints.empty()) {
236 zone.endpoints = endpoints;
237 }
238 if (read_only) {
239 zone.read_only = *read_only;
240 }
241 if (ptier_type) {
242 zone.tier_type = *ptier_type;
243 if (!sync_mgr->get_module(*ptier_type, nullptr)) {
b3b6e05e 244 ldpp_dout(dpp, 0) << "ERROR: could not found sync module: " << *ptier_type
11fdf7f2
TL
245 << ", valid sync modules: "
246 << sync_mgr->get_registered_module_names()
247 << dendl;
248 return -ENOENT;
249 }
250 }
251
252 if (psync_from_all) {
253 zone.sync_from_all = *psync_from_all;
254 }
255
256 if (predirect_zone) {
257 zone.redirect_zone = *predirect_zone;
258 }
259
9f95a23c
TL
260 if (bucket_index_max_shards) {
261 zone.bucket_index_max_shards = *bucket_index_max_shards;
262 }
263
11fdf7f2
TL
264 for (auto add : sync_from) {
265 zone.sync_from.insert(add);
266 }
267
268 for (auto rm : sync_from_rm) {
269 zone.sync_from.erase(rm);
270 }
271
b3b6e05e 272 post_process_params(dpp, y);
11fdf7f2 273
b3b6e05e 274 return update(dpp,y);
11fdf7f2
TL
275}
276
277
b3b6e05e
TL
278int RGWZoneGroup::rename_zone(const DoutPrefixProvider *dpp,
279 const RGWZoneParams& zone_params,
f67539c2
TL
280 optional_yield y)
281{
11fdf7f2
TL
282 RGWZone& zone = zones[zone_params.get_id()];
283 zone.name = zone_params.get_name();
f67539c2 284
b3b6e05e 285 return update(dpp, y);
11fdf7f2
TL
286}
287
b3b6e05e 288void RGWZoneGroup::post_process_params(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
289{
290 bool log_data = zones.size() > 1;
291
292 if (master_zone.empty()) {
9f95a23c 293 auto iter = zones.begin();
11fdf7f2
TL
294 if (iter != zones.end()) {
295 master_zone = iter->first;
296 }
297 }
298
9f95a23c
TL
299 for (auto& item : zones) {
300 RGWZone& zone = item.second;
11fdf7f2
TL
301 zone.log_data = log_data;
302
303 RGWZoneParams zone_params(zone.id, zone.name);
b3b6e05e 304 int ret = zone_params.init(dpp, cct, sysobj_svc, y);
11fdf7f2 305 if (ret < 0) {
b3b6e05e 306 ldpp_dout(dpp, 0) << "WARNING: could not read zone params for zone id=" << zone.id << " name=" << zone.name << dendl;
11fdf7f2
TL
307 continue;
308 }
309
9f95a23c
TL
310 for (auto& pitem : zone_params.placement_pools) {
311 const string& placement_name = pitem.first;
11fdf7f2
TL
312 if (placement_targets.find(placement_name) == placement_targets.end()) {
313 RGWZoneGroupPlacementTarget placement_target;
314 placement_target.name = placement_name;
315 placement_targets[placement_name] = placement_target;
316 }
317 }
318 }
319
320 if (default_placement.empty() && !placement_targets.empty()) {
321 default_placement.init(placement_targets.begin()->first, RGW_STORAGE_CLASS_STANDARD);
322 }
323}
324
b3b6e05e 325int RGWZoneGroup::remove_zone(const DoutPrefixProvider *dpp, const std::string& zone_id, optional_yield y)
11fdf7f2 326{
9f95a23c 327 auto iter = zones.find(zone_id);
11fdf7f2 328 if (iter == zones.end()) {
b3b6e05e 329 ldpp_dout(dpp, 0) << "zone id " << zone_id << " is not a part of zonegroup "
11fdf7f2
TL
330 << name << dendl;
331 return -ENOENT;
332 }
333
334 zones.erase(iter);
335
b3b6e05e 336 post_process_params(dpp, y);
11fdf7f2 337
b3b6e05e 338 return update(dpp, y);
11fdf7f2
TL
339}
340
b3b6e05e 341int RGWZoneGroup::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
f67539c2 342 bool old_format)
11fdf7f2
TL
343{
344 if (realm_id.empty()) {
345 /* try using default realm */
346 RGWRealm realm;
b3b6e05e 347 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
348 // no default realm exist
349 if (ret < 0) {
b3b6e05e 350 return read_id(dpp, default_zonegroup_name, default_id, y);
11fdf7f2
TL
351 }
352 realm_id = realm.get_id();
353 }
354
b3b6e05e 355 return RGWSystemMetaObj::read_default_id(dpp, default_id, y, old_format);
11fdf7f2
TL
356}
357
b3b6e05e 358int RGWZoneGroup::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
359{
360 if (realm_id.empty()) {
361 /* try using default realm */
362 RGWRealm realm;
b3b6e05e 363 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2 364 if (ret < 0) {
b3b6e05e 365 ldpp_dout(dpp, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
366 return -EINVAL;
367 }
368 realm_id = realm.get_id();
369 }
370
b3b6e05e 371 return RGWSystemMetaObj::set_as_default(dpp, y, exclusive);
11fdf7f2
TL
372}
373
374void RGWSystemMetaObj::reinit_instance(CephContext *_cct, RGWSI_SysObj *_sysobj_svc)
375{
376 cct = _cct;
377 sysobj_svc = _sysobj_svc;
378 zone_svc = _sysobj_svc->get_zone_svc();
379}
380
b3b6e05e 381int RGWSystemMetaObj::init(const DoutPrefixProvider *dpp, CephContext *_cct, RGWSI_SysObj *_sysobj_svc,
f67539c2
TL
382 optional_yield y,
383 bool setup_obj, bool old_format)
11fdf7f2
TL
384{
385 reinit_instance(_cct, _sysobj_svc);
386
387 if (!setup_obj)
388 return 0;
389
390 if (old_format && id.empty()) {
391 id = name;
392 }
393
20effc67
TL
394 if (id.empty()) {
395 id = get_predefined_id(cct);
396 }
397
11fdf7f2
TL
398 if (id.empty()) {
399 int r;
400 if (name.empty()) {
401 name = get_predefined_name(cct);
402 }
403 if (name.empty()) {
b3b6e05e 404 r = use_default(dpp, y, old_format);
11fdf7f2
TL
405 if (r < 0) {
406 return r;
407 }
408 } else if (!old_format) {
b3b6e05e 409 r = read_id(dpp, name, id, y);
11fdf7f2
TL
410 if (r < 0) {
411 if (r != -ENOENT) {
b3b6e05e 412 ldpp_dout(dpp, 0) << "error in read_id for object name: " << name << " : " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
413 }
414 return r;
415 }
416 }
417 }
418
b3b6e05e 419 return read_info(dpp, id, y, old_format);
11fdf7f2
TL
420}
421
20effc67
TL
422void RGWDefaultSystemMetaObjInfo::dump(Formatter *f) const {
423 encode_json("default_id", default_id, f);
424}
425
426void RGWDefaultSystemMetaObjInfo::decode_json(JSONObj *obj) {
427 JSONDecoder::decode_json("default_id", default_id, obj);
428}
429
b3b6e05e
TL
430int RGWSystemMetaObj::read_default(const DoutPrefixProvider *dpp,
431 RGWDefaultSystemMetaObjInfo& default_info,
f67539c2 432 const string& oid, optional_yield y)
11fdf7f2
TL
433{
434 using ceph::decode;
435 auto pool = get_pool(cct);
436 bufferlist bl;
437
438 auto obj_ctx = sysobj_svc->init_obj_ctx();
439 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
b3b6e05e 440 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2
TL
441 if (ret < 0)
442 return ret;
443
444 try {
445 auto iter = bl.cbegin();
446 decode(default_info, iter);
447 } catch (buffer::error& err) {
b3b6e05e 448 ldpp_dout(dpp, 0) << "error decoding data from " << pool << ":" << oid << dendl;
11fdf7f2
TL
449 return -EIO;
450 }
451
452 return 0;
453}
454
b3b6e05e 455int RGWSystemMetaObj::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
f67539c2 456 bool old_format)
11fdf7f2
TL
457{
458 RGWDefaultSystemMetaObjInfo default_info;
459
b3b6e05e 460 int ret = read_default(dpp, default_info, get_default_oid(old_format), y);
11fdf7f2
TL
461 if (ret < 0) {
462 return ret;
463 }
464
465 default_id = default_info.default_id;
466
467 return 0;
468}
469
b3b6e05e 470int RGWSystemMetaObj::use_default(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2 471{
b3b6e05e 472 return read_default_id(dpp, id, y, old_format);
11fdf7f2
TL
473}
474
b3b6e05e 475int RGWSystemMetaObj::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
476{
477 using ceph::encode;
478 string oid = get_default_oid();
479
480 rgw_pool pool(get_pool(cct));
481 bufferlist bl;
482
483 RGWDefaultSystemMetaObjInfo default_info;
484 default_info.default_id = id;
485
486 encode(default_info, bl);
487
488 auto obj_ctx = sysobj_svc->init_obj_ctx();
489 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
490 int ret = sysobj.wop()
491 .set_exclusive(exclusive)
b3b6e05e 492 .write(dpp, bl, y);
11fdf7f2
TL
493 if (ret < 0)
494 return ret;
495
496 return 0;
497}
498
b3b6e05e 499int RGWSystemMetaObj::read_id(const DoutPrefixProvider *dpp, const string& obj_name, string& object_id,
f67539c2 500 optional_yield y)
11fdf7f2
TL
501{
502 using ceph::decode;
503 rgw_pool pool(get_pool(cct));
504 bufferlist bl;
505
506 string oid = get_names_oid_prefix() + obj_name;
507
508 auto obj_ctx = sysobj_svc->init_obj_ctx();
509 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
b3b6e05e 510 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2
TL
511 if (ret < 0) {
512 return ret;
513 }
514
515 RGWNameToId nameToId;
516 try {
517 auto iter = bl.cbegin();
518 decode(nameToId, iter);
519 } catch (buffer::error& err) {
b3b6e05e 520 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
11fdf7f2
TL
521 return -EIO;
522 }
523 object_id = nameToId.obj_id;
524 return 0;
525}
526
b3b6e05e 527int RGWSystemMetaObj::delete_obj(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2
TL
528{
529 rgw_pool pool(get_pool(cct));
530
531 auto obj_ctx = sysobj_svc->init_obj_ctx();
532
533 /* check to see if obj is the default */
534 RGWDefaultSystemMetaObjInfo default_info;
b3b6e05e 535 int ret = read_default(dpp, default_info, get_default_oid(old_format), y);
11fdf7f2
TL
536 if (ret < 0 && ret != -ENOENT)
537 return ret;
538 if (default_info.default_id == id || (old_format && default_info.default_id == name)) {
539 string oid = get_default_oid(old_format);
540 rgw_raw_obj default_named_obj(pool, oid);
541 auto sysobj = sysobj_svc->get_obj(obj_ctx, default_named_obj);
b3b6e05e 542 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 543 if (ret < 0) {
b3b6e05e 544 ldpp_dout(dpp, 0) << "Error delete default obj name " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
545 return ret;
546 }
547 }
548 if (!old_format) {
549 string oid = get_names_oid_prefix() + name;
550 rgw_raw_obj object_name(pool, oid);
551 auto sysobj = sysobj_svc->get_obj(obj_ctx, object_name);
b3b6e05e 552 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 553 if (ret < 0) {
b3b6e05e 554 ldpp_dout(dpp, 0) << "Error delete obj name " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
555 return ret;
556 }
557 }
558
559 string oid = get_info_oid_prefix(old_format);
560 if (old_format) {
561 oid += name;
562 } else {
563 oid += id;
564 }
565
566 rgw_raw_obj object_id(pool, oid);
567 auto sysobj = sysobj_svc->get_obj(obj_ctx, object_id);
b3b6e05e 568 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 569 if (ret < 0) {
b3b6e05e 570 ldpp_dout(dpp, 0) << "Error delete object id " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
571 }
572
573 return ret;
574}
575
b3b6e05e 576int RGWSystemMetaObj::store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
577{
578 rgw_pool pool(get_pool(cct));
579 string oid = get_names_oid_prefix() + name;
580
581 RGWNameToId nameToId;
582 nameToId.obj_id = id;
583
584 bufferlist bl;
585 using ceph::encode;
586 encode(nameToId, bl);
587 auto obj_ctx = sysobj_svc->init_obj_ctx();
588 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
589 return sysobj.wop()
590 .set_exclusive(exclusive)
b3b6e05e 591 .write(dpp, bl, y);
11fdf7f2
TL
592}
593
b3b6e05e 594int RGWSystemMetaObj::rename(const DoutPrefixProvider *dpp, const string& new_name, optional_yield y)
11fdf7f2
TL
595{
596 string new_id;
b3b6e05e 597 int ret = read_id(dpp, new_name, new_id, y);
11fdf7f2
TL
598 if (!ret) {
599 return -EEXIST;
600 }
601 if (ret < 0 && ret != -ENOENT) {
b3b6e05e 602 ldpp_dout(dpp, 0) << "Error read_id " << new_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
603 return ret;
604 }
605 string old_name = name;
606 name = new_name;
b3b6e05e 607 ret = update(dpp, y);
11fdf7f2 608 if (ret < 0) {
b3b6e05e 609 ldpp_dout(dpp, 0) << "Error storing new obj info " << new_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
610 return ret;
611 }
b3b6e05e 612 ret = store_name(dpp, true, y);
11fdf7f2 613 if (ret < 0) {
b3b6e05e 614 ldpp_dout(dpp, 0) << "Error storing new name " << new_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
615 return ret;
616 }
617 /* delete old name */
618 rgw_pool pool(get_pool(cct));
619 string oid = get_names_oid_prefix() + old_name;
620 rgw_raw_obj old_name_obj(pool, oid);
621 auto obj_ctx = sysobj_svc->init_obj_ctx();
622 auto sysobj = sysobj_svc->get_obj(obj_ctx, old_name_obj);
b3b6e05e 623 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 624 if (ret < 0) {
b3b6e05e 625 ldpp_dout(dpp, 0) << "Error delete old obj name " << old_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
626 return ret;
627 }
628
629 return ret;
630}
631
b3b6e05e 632int RGWSystemMetaObj::read_info(const DoutPrefixProvider *dpp, const string& obj_id, optional_yield y,
f67539c2 633 bool old_format)
11fdf7f2
TL
634{
635 rgw_pool pool(get_pool(cct));
636
637 bufferlist bl;
638
639 string oid = get_info_oid_prefix(old_format) + obj_id;
640
641 auto obj_ctx = sysobj_svc->init_obj_ctx();
642 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
b3b6e05e 643 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2 644 if (ret < 0) {
b3b6e05e 645 ldpp_dout(dpp, 0) << "failed reading obj info from " << pool << ":" << oid << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
646 return ret;
647 }
648 using ceph::decode;
649
650 try {
651 auto iter = bl.cbegin();
652 decode(*this, iter);
653 } catch (buffer::error& err) {
b3b6e05e 654 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
11fdf7f2
TL
655 return -EIO;
656 }
657
658 return 0;
659}
660
b3b6e05e 661int RGWSystemMetaObj::read(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2 662{
b3b6e05e 663 int ret = read_id(dpp, name, id, y);
11fdf7f2
TL
664 if (ret < 0) {
665 return ret;
666 }
667
b3b6e05e 668 return read_info(dpp, id, y);
11fdf7f2
TL
669}
670
b3b6e05e 671int RGWSystemMetaObj::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
672{
673 int ret;
f67539c2 674
11fdf7f2 675 /* check to see the name is not used */
b3b6e05e 676 ret = read_id(dpp, name, id, y);
11fdf7f2 677 if (exclusive && ret == 0) {
b3b6e05e 678 ldpp_dout(dpp, 10) << "ERROR: name " << name << " already in use for obj id " << id << dendl;
11fdf7f2
TL
679 return -EEXIST;
680 } else if ( ret < 0 && ret != -ENOENT) {
b3b6e05e 681 ldpp_dout(dpp, 0) << "failed reading obj id " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
682 return ret;
683 }
684
685 if (id.empty()) {
686 /* create unique id */
687 uuid_d new_uuid;
688 char uuid_str[37];
689 new_uuid.generate_random();
690 new_uuid.print(uuid_str);
691 id = uuid_str;
692 }
693
b3b6e05e 694 ret = store_info(dpp, exclusive, y);
11fdf7f2 695 if (ret < 0) {
b3b6e05e 696 ldpp_dout(dpp, 0) << "ERROR: storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
697 return ret;
698 }
699
b3b6e05e 700 return store_name(dpp, exclusive, y);
11fdf7f2
TL
701}
702
b3b6e05e 703int RGWSystemMetaObj::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
704{
705 rgw_pool pool(get_pool(cct));
706
707 string oid = get_info_oid_prefix() + id;
708
709 bufferlist bl;
710 using ceph::encode;
711 encode(*this, bl);
712 auto obj_ctx = sysobj_svc->init_obj_ctx();
713 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
714 return sysobj.wop()
715 .set_exclusive(exclusive)
b3b6e05e 716 .write(dpp, bl, y);
11fdf7f2
TL
717}
718
b3b6e05e 719int RGWSystemMetaObj::write(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2 720{
b3b6e05e 721 int ret = store_info(dpp, exclusive, y);
11fdf7f2 722 if (ret < 0) {
b3b6e05e 723 ldpp_dout(dpp, 20) << __func__ << "(): store_info() returned ret=" << ret << dendl;
11fdf7f2
TL
724 return ret;
725 }
b3b6e05e 726 ret = store_name(dpp, exclusive, y);
11fdf7f2 727 if (ret < 0) {
b3b6e05e 728 ldpp_dout(dpp, 20) << __func__ << "(): store_name() returned ret=" << ret << dendl;
11fdf7f2
TL
729 return ret;
730 }
731 return 0;
732}
733
734
20effc67
TL
735RGWRealm::~RGWRealm() {}
736
737RGWRemoteMetaLog::~RGWRemoteMetaLog()
738{
739 delete error_logger;
740}
741
742string RGWRealm::get_predefined_id(CephContext *cct) const {
743 return cct->_conf.get_val<string>("rgw_realm_id");
744}
745
11fdf7f2
TL
746const string& RGWRealm::get_predefined_name(CephContext *cct) const {
747 return cct->_conf->rgw_realm;
748}
749
b3b6e05e 750int RGWRealm::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2 751{
b3b6e05e 752 int ret = RGWSystemMetaObj::create(dpp, y, exclusive);
11fdf7f2 753 if (ret < 0) {
b3b6e05e 754 ldpp_dout(dpp, 0) << "ERROR creating new realm object " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
755 return ret;
756 }
757 // create the control object for watch/notify
b3b6e05e 758 ret = create_control(dpp, exclusive, y);
11fdf7f2 759 if (ret < 0) {
b3b6e05e 760 ldpp_dout(dpp, 0) << "ERROR creating control for new realm " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
761 return ret;
762 }
763 RGWPeriod period;
764 if (current_period.empty()) {
765 /* create new period for the realm */
b3b6e05e 766 ret = period.init(dpp, cct, sysobj_svc, id, y, name, false);
11fdf7f2
TL
767 if (ret < 0 ) {
768 return ret;
769 }
b3b6e05e 770 ret = period.create(dpp, y, true);
11fdf7f2 771 if (ret < 0) {
b3b6e05e 772 ldpp_dout(dpp, 0) << "ERROR: creating new period for realm " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
773 return ret;
774 }
775 } else {
776 period = RGWPeriod(current_period, 0);
b3b6e05e 777 int ret = period.init(dpp, cct, sysobj_svc, id, y, name);
11fdf7f2 778 if (ret < 0) {
b3b6e05e 779 ldpp_dout(dpp, 0) << "ERROR: failed to init period " << current_period << dendl;
11fdf7f2
TL
780 return ret;
781 }
782 }
b3b6e05e 783 ret = set_current_period(dpp, period, y);
11fdf7f2 784 if (ret < 0) {
b3b6e05e 785 ldpp_dout(dpp, 0) << "ERROR: failed set current period " << current_period << dendl;
11fdf7f2
TL
786 return ret;
787 }
788 // try to set as default. may race with another create, so pass exclusive=true
789 // so we don't override an existing default
b3b6e05e 790 ret = set_as_default(dpp, y, true);
11fdf7f2 791 if (ret < 0 && ret != -EEXIST) {
b3b6e05e 792 ldpp_dout(dpp, 0) << "WARNING: failed to set realm as default realm, ret=" << ret << dendl;
11fdf7f2
TL
793 }
794
795 return 0;
796}
797
b3b6e05e 798int RGWRealm::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2 799{
b3b6e05e 800 int ret = RGWSystemMetaObj::delete_obj(dpp, y);
11fdf7f2
TL
801 if (ret < 0) {
802 return ret;
803 }
b3b6e05e 804 return delete_control(dpp, y);
11fdf7f2
TL
805}
806
b3b6e05e 807int RGWRealm::create_control(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
808{
809 auto pool = rgw_pool{get_pool(cct)};
810 auto oid = get_control_oid();
811 bufferlist bl;
812 auto obj_ctx = sysobj_svc->init_obj_ctx();
813 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
814 return sysobj.wop()
815 .set_exclusive(exclusive)
b3b6e05e 816 .write(dpp, bl, y);
11fdf7f2
TL
817}
818
b3b6e05e 819int RGWRealm::delete_control(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
820{
821 auto pool = rgw_pool{get_pool(cct)};
822 auto obj = rgw_raw_obj{pool, get_control_oid()};
823 auto obj_ctx = sysobj_svc->init_obj_ctx();
824 auto sysobj = sysobj_svc->get_obj(obj_ctx, obj);
b3b6e05e 825 return sysobj.wop().remove(dpp, y);
11fdf7f2
TL
826}
827
828rgw_pool RGWRealm::get_pool(CephContext *cct) const
829{
830 if (cct->_conf->rgw_realm_root_pool.empty()) {
831 return rgw_pool(RGW_DEFAULT_REALM_ROOT_POOL);
832 }
833 return rgw_pool(cct->_conf->rgw_realm_root_pool);
834}
835
836const string RGWRealm::get_default_oid(bool old_format) const
837{
838 if (cct->_conf->rgw_default_realm_info_oid.empty()) {
839 return default_realm_info_oid;
840 }
841 return cct->_conf->rgw_default_realm_info_oid;
842}
843
844const string& RGWRealm::get_names_oid_prefix() const
845{
846 return realm_names_oid_prefix;
847}
848
849const string& RGWRealm::get_info_oid_prefix(bool old_format) const
850{
851 return realm_info_oid_prefix;
852}
853
b3b6e05e 854int RGWRealm::set_current_period(const DoutPrefixProvider *dpp, RGWPeriod& period, optional_yield y)
11fdf7f2
TL
855{
856 // update realm epoch to match the period's
857 if (epoch > period.get_realm_epoch()) {
b3b6e05e 858 ldpp_dout(dpp, 0) << "ERROR: set_current_period with old realm epoch "
11fdf7f2
TL
859 << period.get_realm_epoch() << ", current epoch=" << epoch << dendl;
860 return -EINVAL;
861 }
862 if (epoch == period.get_realm_epoch() && current_period != period.get_id()) {
b3b6e05e 863 ldpp_dout(dpp, 0) << "ERROR: set_current_period with same realm epoch "
11fdf7f2
TL
864 << period.get_realm_epoch() << ", but different period id "
865 << period.get_id() << " != " << current_period << dendl;
866 return -EINVAL;
867 }
868
869 epoch = period.get_realm_epoch();
870 current_period = period.get_id();
871
b3b6e05e 872 int ret = update(dpp, y);
11fdf7f2 873 if (ret < 0) {
b3b6e05e 874 ldpp_dout(dpp, 0) << "ERROR: period update: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
875 return ret;
876 }
877
b3b6e05e 878 ret = period.reflect(dpp, y);
11fdf7f2 879 if (ret < 0) {
b3b6e05e 880 ldpp_dout(dpp, 0) << "ERROR: period.reflect(): " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
881 return ret;
882 }
883
884 return 0;
885}
886
887string RGWRealm::get_control_oid() const
888{
889 return get_info_oid_prefix() + id + ".control";
890}
891
b3b6e05e 892int RGWRealm::notify_zone(const DoutPrefixProvider *dpp, bufferlist& bl, optional_yield y)
11fdf7f2
TL
893{
894 rgw_pool pool{get_pool(cct)};
895 auto obj_ctx = sysobj_svc->init_obj_ctx();
896 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, get_control_oid()});
b3b6e05e 897 int ret = sysobj.wn().notify(dpp, bl, 0, nullptr, y);
11fdf7f2
TL
898 if (ret < 0) {
899 return ret;
900 }
901 return 0;
902}
903
b3b6e05e 904int RGWRealm::notify_new_period(const DoutPrefixProvider *dpp, const RGWPeriod& period, optional_yield y)
11fdf7f2
TL
905{
906 bufferlist bl;
907 using ceph::encode;
908 // push the period to dependent zonegroups/zones
909 encode(RGWRealmNotify::ZonesNeedPeriod, bl);
910 encode(period, bl);
911 // reload the gateway with the new period
912 encode(RGWRealmNotify::Reload, bl);
913
b3b6e05e 914 return notify_zone(dpp, bl, y);
11fdf7f2
TL
915}
916
20effc67
TL
917
918int RGWRealm::find_zone(const DoutPrefixProvider *dpp,
919 const rgw_zone_id& zid,
920 RGWPeriod *pperiod,
921 RGWZoneGroup *pzonegroup,
922 bool *pfound,
923 optional_yield y) const
924{
925 auto& found = *pfound;
926
927 found = false;
928
929 string period_id;
930 epoch_t epoch = 0;
931
932 RGWPeriod period(period_id, epoch);
933 int r = period.init(dpp, cct, sysobj_svc, get_id(), y, get_name());
934 if (r < 0) {
935 ldpp_dout(dpp, 0) << "WARNING: period init failed: " << cpp_strerror(-r) << " ... skipping" << dendl;
936 return r;
937 }
938
939 found = period.find_zone(dpp, zid, pzonegroup, y);
940 if (found) {
941 *pperiod = period;
942 }
943 return 0;
944}
945
11fdf7f2
TL
946std::string RGWPeriodConfig::get_oid(const std::string& realm_id)
947{
948 if (realm_id.empty()) {
949 return "period_config.default";
950 }
951 return "period_config." + realm_id;
952}
953
954rgw_pool RGWPeriodConfig::get_pool(CephContext *cct)
955{
956 const auto& pool_name = cct->_conf->rgw_period_root_pool;
957 if (pool_name.empty()) {
958 return {RGW_DEFAULT_PERIOD_ROOT_POOL};
959 }
960 return {pool_name};
961}
962
b3b6e05e 963int RGWPeriodConfig::read(const DoutPrefixProvider *dpp, RGWSI_SysObj *sysobj_svc, const std::string& realm_id,
f67539c2 964 optional_yield y)
11fdf7f2
TL
965{
966 const auto& pool = get_pool(sysobj_svc->ctx());
967 const auto& oid = get_oid(realm_id);
968 bufferlist bl;
969
970 auto obj_ctx = sysobj_svc->init_obj_ctx();
971 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
b3b6e05e 972 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2
TL
973 if (ret < 0) {
974 return ret;
975 }
976 using ceph::decode;
977 try {
978 auto iter = bl.cbegin();
979 decode(*this, iter);
980 } catch (buffer::error& err) {
981 return -EIO;
982 }
983 return 0;
984}
985
b3b6e05e
TL
986int RGWPeriodConfig::write(const DoutPrefixProvider *dpp,
987 RGWSI_SysObj *sysobj_svc,
f67539c2 988 const std::string& realm_id, optional_yield y)
11fdf7f2
TL
989{
990 const auto& pool = get_pool(sysobj_svc->ctx());
991 const auto& oid = get_oid(realm_id);
992 bufferlist bl;
993 using ceph::encode;
994 encode(*this, bl);
995 auto obj_ctx = sysobj_svc->init_obj_ctx();
996 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
997 return sysobj.wop()
998 .set_exclusive(false)
b3b6e05e 999 .write(dpp, bl, y);
11fdf7f2
TL
1000}
1001
b3b6e05e 1002int RGWPeriod::init(const DoutPrefixProvider *dpp, CephContext *_cct, RGWSI_SysObj *_sysobj_svc,
f67539c2 1003 const string& period_realm_id, optional_yield y,
11fdf7f2
TL
1004 const string& period_realm_name, bool setup_obj)
1005{
1006 cct = _cct;
1007 sysobj_svc = _sysobj_svc;
1008
1009 realm_id = period_realm_id;
1010 realm_name = period_realm_name;
1011
1012 if (!setup_obj)
1013 return 0;
1014
b3b6e05e 1015 return init(dpp, _cct, _sysobj_svc, y, setup_obj);
11fdf7f2
TL
1016}
1017
1018
b3b6e05e
TL
1019int RGWPeriod::init(const DoutPrefixProvider *dpp,
1020 CephContext *_cct, RGWSI_SysObj *_sysobj_svc,
f67539c2 1021 optional_yield y, bool setup_obj)
11fdf7f2
TL
1022{
1023 cct = _cct;
1024 sysobj_svc = _sysobj_svc;
1025
1026 if (!setup_obj)
1027 return 0;
1028
1029 if (id.empty()) {
1030 RGWRealm realm(realm_id, realm_name);
b3b6e05e 1031 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2 1032 if (ret < 0) {
20effc67 1033 ldpp_dout(dpp, 4) << "RGWPeriod::init failed to init realm " << realm_name << " id " << realm_id << " : " <<
11fdf7f2
TL
1034 cpp_strerror(-ret) << dendl;
1035 return ret;
1036 }
1037 id = realm.get_current_period();
1038 realm_id = realm.get_id();
1039 }
1040
1041 if (!epoch) {
b3b6e05e 1042 int ret = use_latest_epoch(dpp, y);
11fdf7f2 1043 if (ret < 0) {
b3b6e05e 1044 ldpp_dout(dpp, 0) << "failed to use_latest_epoch period id " << id << " realm " << realm_name << " id " << realm_id
11fdf7f2
TL
1045 << " : " << cpp_strerror(-ret) << dendl;
1046 return ret;
1047 }
1048 }
1049
b3b6e05e 1050 return read_info(dpp, y);
11fdf7f2
TL
1051}
1052
1053
1054int RGWPeriod::get_zonegroup(RGWZoneGroup& zonegroup,
1055 const string& zonegroup_id) const
1056{
1057 map<string, RGWZoneGroup>::const_iterator iter;
1058 if (!zonegroup_id.empty()) {
1059 iter = period_map.zonegroups.find(zonegroup_id);
1060 } else {
1061 iter = period_map.zonegroups.find("default");
1062 }
1063 if (iter != period_map.zonegroups.end()) {
1064 zonegroup = iter->second;
1065 return 0;
1066 }
1067
1068 return -ENOENT;
1069}
1070
20effc67
TL
1071bool RGWPeriod::find_zone(const DoutPrefixProvider *dpp,
1072 const rgw_zone_id& zid,
1073 RGWZoneGroup *pzonegroup,
1074 optional_yield y) const
1075{
1076 RGWZoneGroup zg;
1077 RGWZone zone;
1078
1079 bool found = period_map.find_zone_by_id(zid, &zg, &zone);
1080 if (found) {
1081 *pzonegroup = zg;
1082 }
1083
1084 return found;
1085}
1086
11fdf7f2
TL
1087const string& RGWPeriod::get_latest_epoch_oid() const
1088{
1089 if (cct->_conf->rgw_period_latest_epoch_info_oid.empty()) {
1090 return period_latest_epoch_info_oid;
1091 }
1092 return cct->_conf->rgw_period_latest_epoch_info_oid;
1093}
1094
1095const string& RGWPeriod::get_info_oid_prefix() const
1096{
1097 return period_info_oid_prefix;
1098}
1099
1100const string RGWPeriod::get_period_oid_prefix() const
1101{
1102 return get_info_oid_prefix() + id;
1103}
1104
1105const string RGWPeriod::get_period_oid() const
1106{
1107 std::ostringstream oss;
1108 oss << get_period_oid_prefix();
1109 // skip the epoch for the staging period
1110 if (id != get_staging_id(realm_id))
1111 oss << "." << epoch;
1112 return oss.str();
1113}
1114
b3b6e05e
TL
1115int RGWPeriod::read_latest_epoch(const DoutPrefixProvider *dpp,
1116 RGWPeriodLatestEpochInfo& info,
f67539c2 1117 optional_yield y,
11fdf7f2
TL
1118 RGWObjVersionTracker *objv)
1119{
1120 string oid = get_period_oid_prefix() + get_latest_epoch_oid();
1121
1122 rgw_pool pool(get_pool(cct));
1123 bufferlist bl;
1124 auto obj_ctx = sysobj_svc->init_obj_ctx();
1125 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
b3b6e05e 1126 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2 1127 if (ret < 0) {
b3b6e05e 1128 ldpp_dout(dpp, 1) << "error read_lastest_epoch " << pool << ":" << oid << dendl;
11fdf7f2
TL
1129 return ret;
1130 }
1131 try {
1132 auto iter = bl.cbegin();
1133 using ceph::decode;
1134 decode(info, iter);
1135 } catch (buffer::error& err) {
b3b6e05e 1136 ldpp_dout(dpp, 0) << "error decoding data from " << pool << ":" << oid << dendl;
11fdf7f2
TL
1137 return -EIO;
1138 }
1139
1140 return 0;
1141}
1142
b3b6e05e 1143int RGWPeriod::get_latest_epoch(const DoutPrefixProvider *dpp, epoch_t& latest_epoch, optional_yield y)
11fdf7f2
TL
1144{
1145 RGWPeriodLatestEpochInfo info;
1146
b3b6e05e 1147 int ret = read_latest_epoch(dpp, info, y);
11fdf7f2
TL
1148 if (ret < 0) {
1149 return ret;
1150 }
1151
1152 latest_epoch = info.epoch;
1153
1154 return 0;
1155}
1156
b3b6e05e 1157int RGWPeriod::use_latest_epoch(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1158{
1159 RGWPeriodLatestEpochInfo info;
b3b6e05e 1160 int ret = read_latest_epoch(dpp, info, y);
11fdf7f2
TL
1161 if (ret < 0) {
1162 return ret;
1163 }
1164
1165 epoch = info.epoch;
1166
1167 return 0;
1168}
1169
b3b6e05e
TL
1170int RGWPeriod::set_latest_epoch(const DoutPrefixProvider *dpp,
1171 optional_yield y,
f67539c2 1172 epoch_t epoch, bool exclusive,
11fdf7f2
TL
1173 RGWObjVersionTracker *objv)
1174{
1175 string oid = get_period_oid_prefix() + get_latest_epoch_oid();
1176
1177 rgw_pool pool(get_pool(cct));
1178 bufferlist bl;
1179
1180 RGWPeriodLatestEpochInfo info;
1181 info.epoch = epoch;
1182
1183 using ceph::encode;
1184 encode(info, bl);
1185
1186 auto obj_ctx = sysobj_svc->init_obj_ctx();
1187 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
1188 return sysobj.wop()
1189 .set_exclusive(exclusive)
b3b6e05e 1190 .write(dpp, bl, y);
11fdf7f2
TL
1191}
1192
b3b6e05e 1193int RGWPeriod::update_latest_epoch(const DoutPrefixProvider *dpp, epoch_t epoch, optional_yield y)
11fdf7f2
TL
1194{
1195 static constexpr int MAX_RETRIES = 20;
1196
1197 for (int i = 0; i < MAX_RETRIES; i++) {
1198 RGWPeriodLatestEpochInfo info;
1199 RGWObjVersionTracker objv;
1200 bool exclusive = false;
1201
1202 // read existing epoch
b3b6e05e 1203 int r = read_latest_epoch(dpp, info, y, &objv);
11fdf7f2
TL
1204 if (r == -ENOENT) {
1205 // use an exclusive create to set the epoch atomically
1206 exclusive = true;
b3b6e05e 1207 ldpp_dout(dpp, 20) << "creating initial latest_epoch=" << epoch
11fdf7f2
TL
1208 << " for period=" << id << dendl;
1209 } else if (r < 0) {
b3b6e05e 1210 ldpp_dout(dpp, 0) << "ERROR: failed to read latest_epoch" << dendl;
11fdf7f2
TL
1211 return r;
1212 } else if (epoch <= info.epoch) {
1213 r = -EEXIST; // fail with EEXIST if epoch is not newer
b3b6e05e 1214 ldpp_dout(dpp, 10) << "found existing latest_epoch " << info.epoch
11fdf7f2
TL
1215 << " >= given epoch " << epoch << ", returning r=" << r << dendl;
1216 return r;
1217 } else {
b3b6e05e 1218 ldpp_dout(dpp, 20) << "updating latest_epoch from " << info.epoch
11fdf7f2
TL
1219 << " -> " << epoch << " on period=" << id << dendl;
1220 }
1221
b3b6e05e 1222 r = set_latest_epoch(dpp, y, epoch, exclusive, &objv);
11fdf7f2
TL
1223 if (r == -EEXIST) {
1224 continue; // exclusive create raced with another update, retry
1225 } else if (r == -ECANCELED) {
1226 continue; // write raced with a conflicting version, retry
1227 }
1228 if (r < 0) {
b3b6e05e 1229 ldpp_dout(dpp, 0) << "ERROR: failed to write latest_epoch" << dendl;
11fdf7f2
TL
1230 return r;
1231 }
1232 return 0; // return success
1233 }
1234
1235 return -ECANCELED; // fail after max retries
1236}
1237
b3b6e05e 1238int RGWPeriod::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1239{
1240 rgw_pool pool(get_pool(cct));
1241
1242 // delete the object for each period epoch
1243 for (epoch_t e = 1; e <= epoch; e++) {
1244 RGWPeriod p{get_id(), e};
1245 rgw_raw_obj oid{pool, p.get_period_oid()};
1246 auto obj_ctx = sysobj_svc->init_obj_ctx();
1247 auto sysobj = sysobj_svc->get_obj(obj_ctx, oid);
b3b6e05e 1248 int ret = sysobj.wop().remove(dpp, y);
11fdf7f2 1249 if (ret < 0) {
b3b6e05e 1250 ldpp_dout(dpp, 0) << "WARNING: failed to delete period object " << oid
11fdf7f2
TL
1251 << ": " << cpp_strerror(-ret) << dendl;
1252 }
1253 }
1254
1255 // delete the .latest_epoch object
1256 rgw_raw_obj oid{pool, get_period_oid_prefix() + get_latest_epoch_oid()};
1257 auto obj_ctx = sysobj_svc->init_obj_ctx();
1258 auto sysobj = sysobj_svc->get_obj(obj_ctx, oid);
b3b6e05e 1259 int ret = sysobj.wop().remove(dpp, y);
11fdf7f2 1260 if (ret < 0) {
b3b6e05e 1261 ldpp_dout(dpp, 0) << "WARNING: failed to delete period object " << oid
11fdf7f2
TL
1262 << ": " << cpp_strerror(-ret) << dendl;
1263 }
1264 return ret;
1265}
1266
b3b6e05e 1267int RGWPeriod::read_info(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1268{
1269 rgw_pool pool(get_pool(cct));
1270
1271 bufferlist bl;
1272
1273 auto obj_ctx = sysobj_svc->init_obj_ctx();
1274 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, get_period_oid()});
b3b6e05e 1275 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2 1276 if (ret < 0) {
b3b6e05e 1277 ldpp_dout(dpp, 0) << "failed reading obj info from " << pool << ":" << get_period_oid() << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1278 return ret;
1279 }
1280
1281 try {
1282 using ceph::decode;
1283 auto iter = bl.cbegin();
1284 decode(*this, iter);
1285 } catch (buffer::error& err) {
b3b6e05e 1286 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << get_period_oid() << dendl;
11fdf7f2
TL
1287 return -EIO;
1288 }
1289
1290 return 0;
1291}
1292
b3b6e05e 1293int RGWPeriod::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
1294{
1295 int ret;
1296
1297 /* create unique id */
1298 uuid_d new_uuid;
1299 char uuid_str[37];
1300 new_uuid.generate_random();
1301 new_uuid.print(uuid_str);
1302 id = uuid_str;
1303
1304 epoch = FIRST_EPOCH;
1305
1306 period_map.id = id;
f67539c2 1307
b3b6e05e 1308 ret = store_info(dpp, exclusive, y);
11fdf7f2 1309 if (ret < 0) {
b3b6e05e 1310 ldpp_dout(dpp, 0) << "ERROR: storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1311 return ret;
1312 }
1313
b3b6e05e 1314 ret = set_latest_epoch(dpp, y, epoch);
11fdf7f2 1315 if (ret < 0) {
b3b6e05e 1316 ldpp_dout(dpp, 0) << "ERROR: setting latest epoch " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1317 }
1318
1319 return ret;
1320}
1321
b3b6e05e 1322int RGWPeriod::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
1323{
1324 rgw_pool pool(get_pool(cct));
1325
1326 string oid = get_period_oid();
1327 bufferlist bl;
1328 using ceph::encode;
1329 encode(*this, bl);
1330
1331 auto obj_ctx = sysobj_svc->init_obj_ctx();
1332 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
1333 return sysobj.wop()
1334 .set_exclusive(exclusive)
b3b6e05e 1335 .write(dpp, bl, y);
11fdf7f2
TL
1336}
1337
1338rgw_pool RGWPeriod::get_pool(CephContext *cct) const
1339{
1340 if (cct->_conf->rgw_period_root_pool.empty()) {
1341 return rgw_pool(RGW_DEFAULT_PERIOD_ROOT_POOL);
1342 }
1343 return rgw_pool(cct->_conf->rgw_period_root_pool);
1344}
1345
b3b6e05e 1346int RGWPeriod::add_zonegroup(const DoutPrefixProvider *dpp, const RGWZoneGroup& zonegroup, optional_yield y)
11fdf7f2
TL
1347{
1348 if (zonegroup.realm_id != realm_id) {
1349 return 0;
1350 }
1351 int ret = period_map.update(zonegroup, cct);
1352 if (ret < 0) {
b3b6e05e 1353 ldpp_dout(dpp, 0) << "ERROR: updating period map: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1354 return ret;
1355 }
1356
b3b6e05e 1357 return store_info(dpp, false, y);
11fdf7f2
TL
1358}
1359
b3b6e05e 1360int RGWPeriod::update(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1361{
1362 auto zone_svc = sysobj_svc->get_zone_svc();
b3b6e05e 1363 ldpp_dout(dpp, 20) << __func__ << " realm " << realm_id << " period " << get_id() << dendl;
11fdf7f2 1364 list<string> zonegroups;
b3b6e05e 1365 int ret = zone_svc->list_zonegroups(dpp, zonegroups);
11fdf7f2 1366 if (ret < 0) {
b3b6e05e 1367 ldpp_dout(dpp, 0) << "ERROR: failed to list zonegroups: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1368 return ret;
1369 }
1370
1371 // clear zone short ids of removed zones. period_map.update() will add the
1372 // remaining zones back
1373 period_map.short_zone_ids.clear();
1374
1375 for (auto& iter : zonegroups) {
1376 RGWZoneGroup zg(string(), iter);
b3b6e05e 1377 ret = zg.init(dpp, cct, sysobj_svc, y);
11fdf7f2 1378 if (ret < 0) {
b3b6e05e 1379 ldpp_dout(dpp, 0) << "WARNING: zg.init() failed: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1380 continue;
1381 }
1382
1383 if (zg.realm_id != realm_id) {
b3b6e05e 1384 ldpp_dout(dpp, 20) << "skipping zonegroup " << zg.get_name() << " zone realm id " << zg.realm_id << ", not on our realm " << realm_id << dendl;
11fdf7f2
TL
1385 continue;
1386 }
1387
1388 if (zg.master_zone.empty()) {
b3b6e05e 1389 ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name() << " should have a master zone " << dendl;
11fdf7f2
TL
1390 return -EINVAL;
1391 }
1392
1393 if (zg.zones.find(zg.master_zone) == zg.zones.end()) {
b3b6e05e 1394 ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name()
11fdf7f2
TL
1395 << " has a non existent master zone "<< dendl;
1396 return -EINVAL;
1397 }
1398
1399 if (zg.is_master_zonegroup()) {
1400 master_zonegroup = zg.get_id();
1401 master_zone = zg.master_zone;
1402 }
1403
1404 int ret = period_map.update(zg, cct);
1405 if (ret < 0) {
1406 return ret;
1407 }
1408 }
1409
b3b6e05e 1410 ret = period_config.read(dpp, sysobj_svc, realm_id, y);
11fdf7f2 1411 if (ret < 0 && ret != -ENOENT) {
b3b6e05e 1412 ldpp_dout(dpp, 0) << "ERROR: failed to read period config: "
11fdf7f2
TL
1413 << cpp_strerror(ret) << dendl;
1414 return ret;
1415 }
1416 return 0;
1417}
1418
b3b6e05e 1419int RGWPeriod::reflect(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1420{
1421 for (auto& iter : period_map.zonegroups) {
1422 RGWZoneGroup& zg = iter.second;
1423 zg.reinit_instance(cct, sysobj_svc);
b3b6e05e 1424 int r = zg.write(dpp, false, y);
11fdf7f2 1425 if (r < 0) {
b3b6e05e 1426 ldpp_dout(dpp, 0) << "ERROR: failed to store zonegroup info for zonegroup=" << iter.first << ": " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1427 return r;
1428 }
1429 if (zg.is_master_zonegroup()) {
1430 // set master as default if no default exists
b3b6e05e 1431 r = zg.set_as_default(dpp, y, true);
11fdf7f2 1432 if (r == 0) {
b3b6e05e 1433 ldpp_dout(dpp, 1) << "Set the period's master zonegroup " << zg.get_id()
11fdf7f2
TL
1434 << " as the default" << dendl;
1435 }
1436 }
1437 }
1438
b3b6e05e 1439 int r = period_config.write(dpp, sysobj_svc, realm_id, y);
11fdf7f2 1440 if (r < 0) {
b3b6e05e 1441 ldpp_dout(dpp, 0) << "ERROR: failed to store period config: "
11fdf7f2
TL
1442 << cpp_strerror(-r) << dendl;
1443 return r;
1444 }
1445 return 0;
1446}
1447
1448void RGWPeriod::fork()
1449{
1450 ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << id << dendl;
1451 predecessor_uuid = id;
1452 id = get_staging_id(realm_id);
1453 period_map.reset();
1454 realm_epoch++;
1455}
1456
20effc67 1457static int read_sync_status(const DoutPrefixProvider *dpp, rgw::sal::RadosStore* store, rgw_meta_sync_status *sync_status)
11fdf7f2
TL
1458{
1459 // initialize a sync status manager to read the status
9f95a23c 1460 RGWMetaSyncStatusManager mgr(store, store->svc()->rados->get_async_processor());
b3b6e05e 1461 int r = mgr.init(dpp);
11fdf7f2
TL
1462 if (r < 0) {
1463 return r;
1464 }
b3b6e05e 1465 r = mgr.read_sync_status(dpp, sync_status);
11fdf7f2
TL
1466 mgr.stop();
1467 return r;
1468}
1469
b3b6e05e 1470int RGWPeriod::update_sync_status(const DoutPrefixProvider *dpp,
20effc67 1471 rgw::sal::Store* store, /* for now */
11fdf7f2
TL
1472 const RGWPeriod &current_period,
1473 std::ostream& error_stream,
1474 bool force_if_stale)
1475{
1476 rgw_meta_sync_status status;
20effc67 1477 int r = read_sync_status(dpp, static_cast<rgw::sal::RadosStore*>(store), &status);
11fdf7f2 1478 if (r < 0) {
b3b6e05e 1479 ldpp_dout(dpp, 0) << "period failed to read sync status: "
11fdf7f2
TL
1480 << cpp_strerror(-r) << dendl;
1481 return r;
1482 }
1483
1484 std::vector<std::string> markers;
1485
1486 const auto current_epoch = current_period.get_realm_epoch();
1487 if (current_epoch != status.sync_info.realm_epoch) {
1488 // no sync status markers for the current period
1489 ceph_assert(current_epoch > status.sync_info.realm_epoch);
1490 const int behind = current_epoch - status.sync_info.realm_epoch;
1491 if (!force_if_stale && current_epoch > 1) {
1492 error_stream << "ERROR: This zone is " << behind << " period(s) behind "
1493 "the current master zone in metadata sync. If this zone is promoted "
1494 "to master, any metadata changes during that time are likely to "
1495 "be lost.\n"
1496 "Waiting for this zone to catch up on metadata sync (see "
1497 "'radosgw-admin sync status') is recommended.\n"
1498 "To promote this zone to master anyway, add the flag "
1499 "--yes-i-really-mean-it." << std::endl;
1500 return -EINVAL;
1501 }
1502 // empty sync status markers - other zones will skip this period during
1503 // incremental metadata sync
1504 markers.resize(status.sync_info.num_shards);
1505 } else {
1506 markers.reserve(status.sync_info.num_shards);
1507 for (auto& i : status.sync_markers) {
1508 auto& marker = i.second;
1509 // filter out markers from other periods
1510 if (marker.realm_epoch != current_epoch) {
1511 marker.marker.clear();
1512 }
1513 markers.emplace_back(std::move(marker.marker));
1514 }
1515 }
1516
1517 std::swap(sync_status, markers);
1518 return 0;
1519}
1520
20effc67
TL
1521int RGWPeriod::commit(const DoutPrefixProvider *dpp,
1522 rgw::sal::Store* store,
11fdf7f2 1523 RGWRealm& realm, const RGWPeriod& current_period,
f67539c2
TL
1524 std::ostream& error_stream, optional_yield y,
1525 bool force_if_stale)
11fdf7f2
TL
1526{
1527 auto zone_svc = sysobj_svc->get_zone_svc();
b3b6e05e 1528 ldpp_dout(dpp, 20) << __func__ << " realm " << realm.get_id() << " period " << current_period.get_id() << dendl;
11fdf7f2
TL
1529 // gateway must be in the master zone to commit
1530 if (master_zone != zone_svc->get_zone_params().get_id()) {
1531 error_stream << "Cannot commit period on zone "
1532 << zone_svc->get_zone_params().get_id() << ", it must be sent to "
1533 "the period's master zone " << master_zone << '.' << std::endl;
1534 return -EINVAL;
1535 }
1536 // period predecessor must match current period
1537 if (predecessor_uuid != current_period.get_id()) {
1538 error_stream << "Period predecessor " << predecessor_uuid
1539 << " does not match current period " << current_period.get_id()
1540 << ". Use 'period pull' to get the latest period from the master, "
1541 "reapply your changes, and try again." << std::endl;
1542 return -EINVAL;
1543 }
1544 // realm epoch must be 1 greater than current period
1545 if (realm_epoch != current_period.get_realm_epoch() + 1) {
1546 error_stream << "Period's realm epoch " << realm_epoch
1547 << " does not come directly after current realm epoch "
1548 << current_period.get_realm_epoch() << ". Use 'realm pull' to get the "
1549 "latest realm and period from the master zone, reapply your changes, "
1550 "and try again." << std::endl;
1551 return -EINVAL;
1552 }
1553 // did the master zone change?
1554 if (master_zone != current_period.get_master_zone()) {
1555 // store the current metadata sync status in the period
b3b6e05e 1556 int r = update_sync_status(dpp, store, current_period, error_stream, force_if_stale);
11fdf7f2 1557 if (r < 0) {
b3b6e05e 1558 ldpp_dout(dpp, 0) << "failed to update metadata sync status: "
11fdf7f2
TL
1559 << cpp_strerror(-r) << dendl;
1560 return r;
1561 }
1562 // create an object with a new period id
b3b6e05e 1563 r = create(dpp, y, true);
11fdf7f2 1564 if (r < 0) {
b3b6e05e 1565 ldpp_dout(dpp, 0) << "failed to create new period: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1566 return r;
1567 }
1568 // set as current period
b3b6e05e 1569 r = realm.set_current_period(dpp, *this, y);
11fdf7f2 1570 if (r < 0) {
b3b6e05e 1571 ldpp_dout(dpp, 0) << "failed to update realm's current period: "
11fdf7f2
TL
1572 << cpp_strerror(-r) << dendl;
1573 return r;
1574 }
b3b6e05e 1575 ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period "
11fdf7f2 1576 << id << dendl;
b3b6e05e 1577 realm.notify_new_period(dpp, *this, y);
11fdf7f2
TL
1578 return 0;
1579 }
1580 // period must be based on current epoch
1581 if (epoch != current_period.get_epoch()) {
1582 error_stream << "Period epoch " << epoch << " does not match "
1583 "predecessor epoch " << current_period.get_epoch()
1584 << ". Use 'period pull' to get the latest epoch from the master zone, "
1585 "reapply your changes, and try again." << std::endl;
1586 return -EINVAL;
1587 }
1588 // set period as next epoch
1589 set_id(current_period.get_id());
1590 set_epoch(current_period.get_epoch() + 1);
1591 set_predecessor(current_period.get_predecessor());
1592 realm_epoch = current_period.get_realm_epoch();
1593 // write the period to rados
b3b6e05e 1594 int r = store_info(dpp, false, y);
11fdf7f2 1595 if (r < 0) {
b3b6e05e 1596 ldpp_dout(dpp, 0) << "failed to store period: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1597 return r;
1598 }
1599 // set as latest epoch
b3b6e05e 1600 r = update_latest_epoch(dpp, epoch, y);
11fdf7f2
TL
1601 if (r == -EEXIST) {
1602 // already have this epoch (or a more recent one)
1603 return 0;
1604 }
1605 if (r < 0) {
b3b6e05e 1606 ldpp_dout(dpp, 0) << "failed to set latest epoch: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1607 return r;
1608 }
b3b6e05e 1609 r = reflect(dpp, y);
11fdf7f2 1610 if (r < 0) {
b3b6e05e 1611 ldpp_dout(dpp, 0) << "failed to update local objects: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1612 return r;
1613 }
b3b6e05e 1614 ldpp_dout(dpp, 4) << "Committed new epoch " << epoch
11fdf7f2 1615 << " for period " << id << dendl;
b3b6e05e 1616 realm.notify_new_period(dpp, *this, y);
11fdf7f2
TL
1617 return 0;
1618}
1619
b3b6e05e 1620int RGWZoneParams::create_default(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2
TL
1621{
1622 name = default_zone_name;
1623
b3b6e05e 1624 int r = create(dpp, y);
11fdf7f2
TL
1625 if (r < 0) {
1626 return r;
1627 }
1628
1629 if (old_format) {
1630 name = id;
1631 }
1632
1633 return r;
1634}
1635
20effc67
TL
1636void RGWZoneParams::dump(Formatter *f) const
1637{
1638 RGWSystemMetaObj::dump(f);
1639 encode_json("domain_root", domain_root, f);
1640 encode_json("control_pool", control_pool, f);
1641 encode_json("gc_pool", gc_pool, f);
1642 encode_json("lc_pool", lc_pool, f);
1643 encode_json("log_pool", log_pool, f);
1644 encode_json("intent_log_pool", intent_log_pool, f);
1645 encode_json("usage_log_pool", usage_log_pool, f);
1646 encode_json("roles_pool", roles_pool, f);
1647 encode_json("reshard_pool", reshard_pool, f);
1648 encode_json("user_keys_pool", user_keys_pool, f);
1649 encode_json("user_email_pool", user_email_pool, f);
1650 encode_json("user_swift_pool", user_swift_pool, f);
1651 encode_json("user_uid_pool", user_uid_pool, f);
1652 encode_json("otp_pool", otp_pool, f);
1653 encode_json_plain("system_key", system_key, f);
1654 encode_json("placement_pools", placement_pools, f);
1655 encode_json("tier_config", tier_config, f);
1656 encode_json("realm_id", realm_id, f);
1657 encode_json("notif_pool", notif_pool, f);
1658}
11fdf7f2 1659
f67539c2 1660namespace {
b3b6e05e
TL
1661int get_zones_pool_set(const DoutPrefixProvider *dpp,
1662 CephContext* cct,
11fdf7f2
TL
1663 RGWSI_SysObj* sysobj_svc,
1664 const list<string>& zones,
1665 const string& my_zone_id,
f67539c2
TL
1666 set<rgw_pool>& pool_names,
1667 optional_yield y)
11fdf7f2
TL
1668{
1669 for(auto const& iter : zones) {
1670 RGWZoneParams zone(iter);
b3b6e05e 1671 int r = zone.init(dpp, cct, sysobj_svc, y);
11fdf7f2 1672 if (r < 0) {
b3b6e05e 1673 ldpp_dout(dpp, 0) << "Error: init zone " << iter << ":" << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1674 return r;
1675 }
1676 if (zone.get_id() != my_zone_id) {
1677 pool_names.insert(zone.domain_root);
11fdf7f2
TL
1678 pool_names.insert(zone.control_pool);
1679 pool_names.insert(zone.gc_pool);
1680 pool_names.insert(zone.log_pool);
1681 pool_names.insert(zone.intent_log_pool);
1682 pool_names.insert(zone.usage_log_pool);
1683 pool_names.insert(zone.user_keys_pool);
1684 pool_names.insert(zone.user_email_pool);
1685 pool_names.insert(zone.user_swift_pool);
1686 pool_names.insert(zone.user_uid_pool);
1687 pool_names.insert(zone.otp_pool);
1688 pool_names.insert(zone.roles_pool);
1689 pool_names.insert(zone.reshard_pool);
f67539c2 1690 pool_names.insert(zone.notif_pool);
11fdf7f2
TL
1691 for(auto& iter : zone.placement_pools) {
1692 pool_names.insert(iter.second.index_pool);
1693 for (auto& pi : iter.second.storage_classes.get_all()) {
1694 if (pi.second.data_pool) {
1695 pool_names.insert(pi.second.data_pool.get());
1696 }
1697 }
1698 pool_names.insert(iter.second.data_extra_pool);
1699 }
f91f0fd5 1700 pool_names.insert(zone.oidc_pool);
11fdf7f2
TL
1701 }
1702 }
1703 return 0;
1704}
1705
1706rgw_pool fix_zone_pool_dup(set<rgw_pool> pools,
1707 const string& default_prefix,
1708 const string& default_suffix,
1709 const rgw_pool& suggested_pool)
1710{
1711 string suggested_name = suggested_pool.to_str();
1712
1713 string prefix = default_prefix;
1714 string suffix = default_suffix;
1715
1716 if (!suggested_pool.empty()) {
1717 prefix = suggested_name.substr(0, suggested_name.find("."));
1718 suffix = suggested_name.substr(prefix.length());
1719 }
1720
1721 rgw_pool pool(prefix + suffix);
1722
1723 if (pools.find(pool) == pools.end()) {
1724 return pool;
1725 } else {
1726 while(true) {
1727 pool = prefix + "_" + std::to_string(std::rand()) + suffix;
1728 if (pools.find(pool) == pools.end()) {
1729 return pool;
1730 }
1731 }
1732 }
1733}
f67539c2 1734}
11fdf7f2 1735
b3b6e05e 1736int RGWZoneParams::fix_pool_names(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1737{
1738
1739 list<string> zones;
b3b6e05e 1740 int r = zone_svc->list_zones(dpp, zones);
11fdf7f2 1741 if (r < 0) {
b3b6e05e 1742 ldpp_dout(dpp, 10) << "WARNING: store->list_zones() returned r=" << r << dendl;
11fdf7f2
TL
1743 }
1744
1745 set<rgw_pool> pools;
b3b6e05e 1746 r = get_zones_pool_set(dpp, cct, sysobj_svc, zones, id, pools, y);
11fdf7f2 1747 if (r < 0) {
b3b6e05e 1748 ldpp_dout(dpp, 0) << "Error: get_zones_pool_names" << r << dendl;
11fdf7f2
TL
1749 return r;
1750 }
1751
1752 domain_root = fix_zone_pool_dup(pools, name, ".rgw.meta:root", domain_root);
11fdf7f2
TL
1753 control_pool = fix_zone_pool_dup(pools, name, ".rgw.control", control_pool);
1754 gc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:gc", gc_pool);
1755 lc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:lc", lc_pool);
1756 log_pool = fix_zone_pool_dup(pools, name, ".rgw.log", log_pool);
1757 intent_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:intent", intent_log_pool);
1758 usage_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:usage", usage_log_pool);
1759 user_keys_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.keys", user_keys_pool);
1760 user_email_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.email", user_email_pool);
1761 user_swift_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.swift", user_swift_pool);
1762 user_uid_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.uid", user_uid_pool);
1763 roles_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:roles", roles_pool);
1764 reshard_pool = fix_zone_pool_dup(pools, name, ".rgw.log:reshard", reshard_pool);
1765 otp_pool = fix_zone_pool_dup(pools, name, ".rgw.otp", otp_pool);
f91f0fd5 1766 oidc_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:oidc", oidc_pool);
f67539c2 1767 notif_pool = fix_zone_pool_dup(pools, name ,".rgw.log:notif", notif_pool);
11fdf7f2
TL
1768
1769 for(auto& iter : placement_pools) {
1770 iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix,
1771 iter.second.index_pool);
1772 for (auto& pi : iter.second.storage_classes.get_all()) {
1773 if (pi.second.data_pool) {
1774 rgw_pool& pool = pi.second.data_pool.get();
1775 pool = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
1776 pool);
1777 }
1778 }
1779 iter.second.data_extra_pool= fix_zone_pool_dup(pools, name, "." + default_storage_extra_pool_suffix,
1780 iter.second.data_extra_pool);
1781 }
1782
1783 return 0;
1784}
1785
b3b6e05e 1786int RGWZoneParams::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
1787{
1788 /* check for old pools config */
1789 rgw_raw_obj obj(domain_root, avail_pools);
1790 auto obj_ctx = sysobj_svc->init_obj_ctx();
1791 auto sysobj = sysobj_svc->get_obj(obj_ctx, obj);
b3b6e05e 1792 int r = sysobj.rop().stat(y, dpp);
11fdf7f2 1793 if (r < 0) {
b3b6e05e 1794 ldpp_dout(dpp, 10) << "couldn't find old data placement pools config, setting up new ones for the zone" << dendl;
11fdf7f2
TL
1795 /* a new system, let's set new placement info */
1796 RGWZonePlacementInfo default_placement;
1797 default_placement.index_pool = name + "." + default_bucket_index_pool_suffix;
1798 rgw_pool pool = name + "." + default_storage_pool_suffix;
1799 default_placement.storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &pool, nullptr);
1800 default_placement.data_extra_pool = name + "." + default_storage_extra_pool_suffix;
1801 placement_pools["default-placement"] = default_placement;
1802 }
1803
b3b6e05e 1804 r = fix_pool_names(dpp, y);
11fdf7f2 1805 if (r < 0) {
b3b6e05e 1806 ldpp_dout(dpp, 0) << "ERROR: fix_pool_names returned r=" << r << dendl;
11fdf7f2
TL
1807 return r;
1808 }
1809
b3b6e05e 1810 r = RGWSystemMetaObj::create(dpp, y, exclusive);
11fdf7f2
TL
1811 if (r < 0) {
1812 return r;
1813 }
1814
1815 // try to set as default. may race with another create, so pass exclusive=true
1816 // so we don't override an existing default
b3b6e05e 1817 r = set_as_default(dpp, y, true);
11fdf7f2 1818 if (r < 0 && r != -EEXIST) {
b3b6e05e 1819 ldpp_dout(dpp, 10) << "WARNING: failed to set zone as default, r=" << r << dendl;
11fdf7f2
TL
1820 }
1821
1822 return 0;
1823}
1824
1825rgw_pool RGWZoneParams::get_pool(CephContext *cct) const
1826{
1827 if (cct->_conf->rgw_zone_root_pool.empty()) {
1828 return rgw_pool(RGW_DEFAULT_ZONE_ROOT_POOL);
1829 }
1830
1831 return rgw_pool(cct->_conf->rgw_zone_root_pool);
1832}
1833
1834const string RGWZoneParams::get_default_oid(bool old_format) const
1835{
1836 if (old_format) {
1837 return cct->_conf->rgw_default_zone_info_oid;
1838 }
1839
1840 return cct->_conf->rgw_default_zone_info_oid + "." + realm_id;
1841}
1842
1843const string& RGWZoneParams::get_names_oid_prefix() const
1844{
1845 return zone_names_oid_prefix;
1846}
1847
1848const string& RGWZoneParams::get_info_oid_prefix(bool old_format) const
1849{
1850 return zone_info_oid_prefix;
1851}
1852
20effc67
TL
1853string RGWZoneParams::get_predefined_id(CephContext *cct) const {
1854 return cct->_conf.get_val<string>("rgw_zone_id");
1855}
1856
11fdf7f2
TL
1857const string& RGWZoneParams::get_predefined_name(CephContext *cct) const {
1858 return cct->_conf->rgw_zone;
1859}
1860
b3b6e05e
TL
1861int RGWZoneParams::init(const DoutPrefixProvider *dpp,
1862 CephContext *cct, RGWSI_SysObj *sysobj_svc,
f67539c2 1863 optional_yield y, bool setup_obj, bool old_format)
11fdf7f2
TL
1864{
1865 if (name.empty()) {
1866 name = cct->_conf->rgw_zone;
1867 }
1868
b3b6e05e 1869 return RGWSystemMetaObj::init(dpp, cct, sysobj_svc, y, setup_obj, old_format);
11fdf7f2
TL
1870}
1871
b3b6e05e 1872int RGWZoneParams::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
f67539c2 1873 bool old_format)
11fdf7f2
TL
1874{
1875 if (realm_id.empty()) {
1876 /* try using default realm */
1877 RGWRealm realm;
b3b6e05e 1878 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
1879 //no default realm exist
1880 if (ret < 0) {
b3b6e05e 1881 return read_id(dpp, default_zone_name, default_id, y);
11fdf7f2
TL
1882 }
1883 realm_id = realm.get_id();
1884 }
1885
b3b6e05e 1886 return RGWSystemMetaObj::read_default_id(dpp, default_id, y, old_format);
11fdf7f2
TL
1887}
1888
1889
b3b6e05e 1890int RGWZoneParams::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
1891{
1892 if (realm_id.empty()) {
1893 /* try using default realm */
1894 RGWRealm realm;
b3b6e05e 1895 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2 1896 if (ret < 0) {
b3b6e05e 1897 ldpp_dout(dpp, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1898 return -EINVAL;
1899 }
1900 realm_id = realm.get_id();
1901 }
1902
b3b6e05e 1903 return RGWSystemMetaObj::set_as_default(dpp, y, exclusive);
11fdf7f2
TL
1904}
1905
1906const string& RGWZoneParams::get_compression_type(const rgw_placement_rule& placement_rule) const
1907{
1908 static const std::string NONE{"none"};
1909 auto p = placement_pools.find(placement_rule.name);
1910 if (p == placement_pools.end()) {
1911 return NONE;
1912 }
eafe8130 1913 const auto& type = p->second.get_compression_type(placement_rule.get_storage_class());
11fdf7f2
TL
1914 return !type.empty() ? type : NONE;
1915}
1916
1917void RGWPeriodMap::encode(bufferlist& bl) const {
1918 ENCODE_START(2, 1, bl);
1919 encode(id, bl);
1920 encode(zonegroups, bl);
1921 encode(master_zonegroup, bl);
1922 encode(short_zone_ids, bl);
1923 ENCODE_FINISH(bl);
1924}
1925
1926void RGWPeriodMap::decode(bufferlist::const_iterator& bl) {
1927 DECODE_START(2, bl);
1928 decode(id, bl);
1929 decode(zonegroups, bl);
1930 decode(master_zonegroup, bl);
1931 if (struct_v >= 2) {
1932 decode(short_zone_ids, bl);
1933 }
1934 DECODE_FINISH(bl);
1935
1936 zonegroups_by_api.clear();
1937 for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
1938 iter != zonegroups.end(); ++iter) {
1939 RGWZoneGroup& zonegroup = iter->second;
1940 zonegroups_by_api[zonegroup.api_name] = zonegroup;
1941 if (zonegroup.is_master_zonegroup()) {
1942 master_zonegroup = zonegroup.get_id();
1943 }
1944 }
1945}
1946
1947// run an MD5 hash on the zone_id and return the first 32 bits
1948static uint32_t gen_short_zone_id(const std::string zone_id)
1949{
1950 unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
1951 MD5 hash;
20effc67
TL
1952 // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
1953 hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
11fdf7f2
TL
1954 hash.Update((const unsigned char *)zone_id.c_str(), zone_id.size());
1955 hash.Final(md5);
1956
1957 uint32_t short_id;
1958 memcpy((char *)&short_id, md5, sizeof(short_id));
1959 return std::max(short_id, 1u);
1960}
1961
1962int RGWPeriodMap::update(const RGWZoneGroup& zonegroup, CephContext *cct)
1963{
1964 if (zonegroup.is_master_zonegroup() && (!master_zonegroup.empty() && zonegroup.get_id() != master_zonegroup)) {
1965 ldout(cct,0) << "Error updating periodmap, multiple master zonegroups configured "<< dendl;
1966 ldout(cct,0) << "master zonegroup: " << master_zonegroup << " and " << zonegroup.get_id() <<dendl;
1967 return -EINVAL;
1968 }
1969 map<string, RGWZoneGroup>::iterator iter = zonegroups.find(zonegroup.get_id());
1970 if (iter != zonegroups.end()) {
1971 RGWZoneGroup& old_zonegroup = iter->second;
1972 if (!old_zonegroup.api_name.empty()) {
1973 zonegroups_by_api.erase(old_zonegroup.api_name);
1974 }
1975 }
1976 zonegroups[zonegroup.get_id()] = zonegroup;
1977
1978 if (!zonegroup.api_name.empty()) {
1979 zonegroups_by_api[zonegroup.api_name] = zonegroup;
1980 }
1981
1982 if (zonegroup.is_master_zonegroup()) {
1983 master_zonegroup = zonegroup.get_id();
1984 } else if (master_zonegroup == zonegroup.get_id()) {
1985 master_zonegroup = "";
1986 }
1987
1988 for (auto& i : zonegroup.zones) {
1989 auto& zone = i.second;
1990 if (short_zone_ids.find(zone.id) != short_zone_ids.end()) {
1991 continue;
1992 }
1993 // calculate the zone's short id
1994 uint32_t short_id = gen_short_zone_id(zone.id);
1995
1996 // search for an existing zone with the same short id
1997 for (auto& s : short_zone_ids) {
1998 if (s.second == short_id) {
1999 ldout(cct, 0) << "New zone '" << zone.name << "' (" << zone.id
2000 << ") generates the same short_zone_id " << short_id
2001 << " as existing zone id " << s.first << dendl;
2002 return -EEXIST;
2003 }
2004 }
2005
2006 short_zone_ids[zone.id] = short_id;
2007 }
2008
2009 return 0;
2010}
2011
2012uint32_t RGWPeriodMap::get_zone_short_id(const string& zone_id) const
2013{
2014 auto i = short_zone_ids.find(zone_id);
2015 if (i == short_zone_ids.end()) {
2016 return 0;
2017 }
2018 return i->second;
2019}
2020
20effc67
TL
2021bool RGWPeriodMap::find_zone_by_id(const rgw_zone_id& zone_id,
2022 RGWZoneGroup *zonegroup,
2023 RGWZone *zone) const
2024{
2025 for (auto& iter : zonegroups) {
2026 auto& zg = iter.second;
2027
2028 auto ziter = zg.zones.find(zone_id);
2029 if (ziter != zg.zones.end()) {
2030 *zonegroup = zg;
2031 *zone = ziter->second;
2032 return true;
2033 }
2034 }
2035
2036 return false;
2037}
2038
2039bool RGWPeriodMap::find_zone_by_name(const string& zone_name,
2040 RGWZoneGroup *zonegroup,
2041 RGWZone *zone) const
2042{
2043 for (auto& iter : zonegroups) {
2044 auto& zg = iter.second;
2045 for (auto& ziter : zg.zones) {
2046 auto& z = ziter.second;
2047
2048 if (z.name == zone_name) {
2049 *zonegroup = zg;
2050 *zone = z;
2051 return true;
2052 }
2053 }
2054 }
2055
2056 return false;
2057}
2058
b3b6e05e 2059int RGWZoneGroupMap::read(const DoutPrefixProvider *dpp, CephContext *cct, RGWSI_SysObj *sysobj_svc, optional_yield y)
11fdf7f2
TL
2060{
2061
2062 RGWPeriod period;
b3b6e05e 2063 int ret = period.init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
2064 if (ret < 0) {
2065 cerr << "failed to read current period info: " << cpp_strerror(ret);
2066 return ret;
2067 }
f67539c2 2068
11fdf7f2
TL
2069 bucket_quota = period.get_config().bucket_quota;
2070 user_quota = period.get_config().user_quota;
2071 zonegroups = period.get_map().zonegroups;
2072 zonegroups_by_api = period.get_map().zonegroups_by_api;
2073 master_zonegroup = period.get_map().master_zonegroup;
2074
2075 return 0;
2076}
2077
2078void RGWRegionMap::encode(bufferlist& bl) const {
2079 ENCODE_START( 3, 1, bl);
2080 encode(regions, bl);
2081 encode(master_region, bl);
2082 encode(bucket_quota, bl);
2083 encode(user_quota, bl);
2084 ENCODE_FINISH(bl);
2085}
2086
2087void RGWRegionMap::decode(bufferlist::const_iterator& bl) {
2088 DECODE_START(3, bl);
2089 decode(regions, bl);
2090 decode(master_region, bl);
2091 if (struct_v >= 2)
2092 decode(bucket_quota, bl);
2093 if (struct_v >= 3)
2094 decode(user_quota, bl);
2095 DECODE_FINISH(bl);
2096}
2097
2098void RGWZoneGroupMap::encode(bufferlist& bl) const {
2099 ENCODE_START( 3, 1, bl);
2100 encode(zonegroups, bl);
2101 encode(master_zonegroup, bl);
2102 encode(bucket_quota, bl);
2103 encode(user_quota, bl);
2104 ENCODE_FINISH(bl);
2105}
2106
2107void RGWZoneGroupMap::decode(bufferlist::const_iterator& bl) {
2108 DECODE_START(3, bl);
2109 decode(zonegroups, bl);
2110 decode(master_zonegroup, bl);
2111 if (struct_v >= 2)
2112 decode(bucket_quota, bl);
2113 if (struct_v >= 3)
2114 decode(user_quota, bl);
2115 DECODE_FINISH(bl);
2116
2117 zonegroups_by_api.clear();
2118 for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
2119 iter != zonegroups.end(); ++iter) {
2120 RGWZoneGroup& zonegroup = iter->second;
2121 zonegroups_by_api[zonegroup.api_name] = zonegroup;
2122 if (zonegroup.is_master_zonegroup()) {
2123 master_zonegroup = zonegroup.get_name();
2124 }
2125 }
2126}
2127
20effc67
TL
2128static inline int conf_to_uint64(const JSONFormattable& config, const string& key, uint64_t *pval)
2129{
2130 string sval;
2131 if (config.find(key, &sval)) {
2132 string err;
2133 uint64_t val = strict_strtoll(sval.c_str(), 10, &err);
2134 if (!err.empty()) {
2135 return -EINVAL;
2136 }
2137 *pval = val;
2138 }
2139 return 0;
2140}
2141
2142int RGWZoneGroupPlacementTier::update_params(const JSONFormattable& config)
2143{
2144 int r = -1;
2145
2146 if (config.exists("retain_head_object")) {
2147 string s = config["retain_head_object"];
2148 if (s == "true") {
2149 retain_head_object = true;
2150 } else {
2151 retain_head_object = false;
2152 }
2153 }
2154
2155 if (tier_type == "cloud-s3") {
2156 r = t.s3.update_params(config);
2157 }
2158
2159 return r;
2160}
2161
2162void RGWZoneGroupPlacementTier::dump(Formatter *f) const
2163{
2164 encode_json("tier_type", tier_type, f);
2165 encode_json("storage_class", storage_class, f);
2166 encode_json("retain_head_object", retain_head_object, f);
2167
2168 if (tier_type == "cloud-s3") {
2169 encode_json("s3", t.s3, f);
2170 }
2171}
2172
2173void RGWZoneGroupPlacementTier::decode_json(JSONObj *obj)
2174{
2175 JSONDecoder::decode_json("tier_type", tier_type, obj);
2176 JSONDecoder::decode_json("storage_class", storage_class, obj);
2177 JSONDecoder::decode_json("retain_head_object", retain_head_object, obj);
2178
2179 if (tier_type == "cloud-s3") {
2180 JSONDecoder::decode_json("s3", t.s3, obj);
2181 }
2182}
2183
2184int RGWZoneGroupPlacementTier::clear_params(const JSONFormattable& config)
2185{
2186 if (config.exists("retain_head_object")) {
2187 retain_head_object = false;
2188 }
2189
2190 if (tier_type == "cloud-s3") {
2191 t.s3.clear_params(config);
2192 }
2193
2194 return 0;
2195}
2196
2197int RGWZoneGroupPlacementTierS3::update_params(const JSONFormattable& config)
2198{
2199 int r = -1;
2200
2201 if (config.exists("endpoint")) {
2202 endpoint = config["endpoint"];
2203 }
2204 if (config.exists("target_path")) {
2205 target_path = config["target_path"];
2206 }
2207 if (config.exists("region")) {
2208 region = config["region"];
2209 }
2210 if (config.exists("host_style")) {
2211 string s;
2212 s = config["host_style"];
2213 if (s != "virtual") {
2214 host_style = PathStyle;
2215 } else {
2216 host_style = VirtualStyle;
2217 }
2218 }
2219 if (config.exists("target_storage_class")) {
2220 target_storage_class = config["target_storage_class"];
2221 }
2222 if (config.exists("access_key")) {
2223 key.id = config["access_key"];
2224 }
2225 if (config.exists("secret")) {
2226 key.key = config["secret"];
2227 }
2228 if (config.exists("multipart_sync_threshold")) {
2229 r = conf_to_uint64(config, "multipart_sync_threshold", &multipart_sync_threshold);
2230 if (r < 0) {
2231 multipart_sync_threshold = DEFAULT_MULTIPART_SYNC_PART_SIZE;
2232 }
2233 }
2234
2235 if (config.exists("multipart_min_part_size")) {
2236 r = conf_to_uint64(config, "multipart_min_part_size", &multipart_min_part_size);
2237 if (r < 0) {
2238 multipart_min_part_size = DEFAULT_MULTIPART_SYNC_PART_SIZE;
2239 }
2240 }
2241
2242 if (config.exists("acls")) {
2243 const JSONFormattable& cc = config["acls"];
2244 if (cc.is_array()) {
2245 for (auto& c : cc.array()) {
2246 RGWTierACLMapping m;
2247 m.init(c);
2248 if (!m.source_id.empty()) {
2249 acl_mappings[m.source_id] = m;
2250 }
2251 }
2252 } else {
2253 RGWTierACLMapping m;
2254 m.init(cc);
2255 if (!m.source_id.empty()) {
2256 acl_mappings[m.source_id] = m;
2257 }
2258 }
2259 }
2260 return 0;
2261}
2262
2263void RGWZoneGroupPlacementTierS3::dump(Formatter *f) const
2264{
2265 encode_json("endpoint", endpoint, f);
2266 encode_json("access_key", key.id, f);
2267 encode_json("secret", key.key, f);
2268 encode_json("region", region, f);
2269 string s = (host_style == PathStyle ? "path" : "virtual");
2270 encode_json("host_style", s, f);
2271 encode_json("target_storage_class", target_storage_class, f);
2272 encode_json("target_path", target_path, f);
2273 encode_json("acl_mappings", acl_mappings, f);
2274 encode_json("multipart_sync_threshold", multipart_sync_threshold, f);
2275 encode_json("multipart_min_part_size", multipart_min_part_size, f);
2276}
2277
2278void RGWZoneGroupPlacementTierS3::decode_json(JSONObj *obj)
2279{
2280 JSONDecoder::decode_json("endpoint", endpoint, obj);
2281 JSONDecoder::decode_json("access_key", key.id, obj);
2282 JSONDecoder::decode_json("secret", key.key, obj);
2283 JSONDecoder::decode_json("region", region, obj);
2284 string s;
2285 JSONDecoder::decode_json("host_style", s, obj);
2286 if (s != "virtual") {
2287 host_style = PathStyle;
2288 } else {
2289 host_style = VirtualStyle;
2290 }
2291 JSONDecoder::decode_json("target_storage_class", target_storage_class, obj);
2292 JSONDecoder::decode_json("target_path", target_path, obj);
2293 JSONDecoder::decode_json("acl_mappings", acl_mappings, obj);
2294 JSONDecoder::decode_json("multipart_sync_threshold", multipart_sync_threshold, obj);
2295 JSONDecoder::decode_json("multipart_min_part_size", multipart_min_part_size, obj);
2296}
2297
2298int RGWZoneGroupPlacementTierS3::clear_params(const JSONFormattable& config)
2299{
2300 if (config.exists("endpoint")) {
2301 endpoint.clear();
2302 }
2303 if (config.exists("target_path")) {
2304 target_path.clear();
2305 }
2306 if (config.exists("region")) {
2307 region.clear();
2308 }
2309 if (config.exists("host_style")) {
2310 /* default */
2311 host_style = PathStyle;
2312 }
2313 if (config.exists("target_storage_class")) {
2314 target_storage_class.clear();
2315 }
2316 if (config.exists("access_key")) {
2317 key.id.clear();
2318 }
2319 if (config.exists("secret")) {
2320 key.key.clear();
2321 }
2322 if (config.exists("multipart_sync_threshold")) {
2323 multipart_sync_threshold = DEFAULT_MULTIPART_SYNC_PART_SIZE;
2324 }
2325 if (config.exists("multipart_min_part_size")) {
2326 multipart_min_part_size = DEFAULT_MULTIPART_SYNC_PART_SIZE;
2327 }
2328 if (config.exists("acls")) {
2329 const JSONFormattable& cc = config["acls"];
2330 if (cc.is_array()) {
2331 for (auto& c : cc.array()) {
2332 RGWTierACLMapping m;
2333 m.init(c);
2334 acl_mappings.erase(m.source_id);
2335 }
2336 } else {
2337 RGWTierACLMapping m;
2338 m.init(cc);
2339 acl_mappings.erase(m.source_id);
2340 }
2341 }
2342 return 0;
2343}
2344
2345void RGWZoneGroupPlacementTarget::dump(Formatter *f) const
2346{
2347 encode_json("name", name, f);
2348 encode_json("tags", tags, f);
2349 encode_json("storage_classes", storage_classes, f);
2350 if (!tier_targets.empty()) {
2351 encode_json("tier_targets", tier_targets, f);
2352 }
2353}
2354
2355void RGWZoneGroupPlacementTarget::decode_json(JSONObj *obj)
2356{
2357 JSONDecoder::decode_json("name", name, obj);
2358 JSONDecoder::decode_json("tags", tags, obj);
2359 JSONDecoder::decode_json("storage_classes", storage_classes, obj);
2360 if (storage_classes.empty()) {
2361 storage_classes.insert(RGW_STORAGE_CLASS_STANDARD);
2362 }
2363 if (!tier_targets.empty()) {
2364 JSONDecoder::decode_json("tier_targets", tier_targets, obj);
2365 }
2366}
2367
2368void RGWZoneGroup::dump(Formatter *f) const
2369{
2370 RGWSystemMetaObj::dump(f);
2371 encode_json("api_name", api_name, f);
2372 encode_json("is_master", is_master, f);
2373 encode_json("endpoints", endpoints, f);
2374 encode_json("hostnames", hostnames, f);
2375 encode_json("hostnames_s3website", hostnames_s3website, f);
2376 encode_json("master_zone", master_zone, f);
2377 encode_json_map("zones", zones, f); /* more friendly representation */
2378 encode_json_map("placement_targets", placement_targets, f); /* more friendly representation */
2379 encode_json("default_placement", default_placement, f);
2380 encode_json("realm_id", realm_id, f);
2381 encode_json("sync_policy", sync_policy, f);
2382}
2383
2384static void decode_zones(map<rgw_zone_id, RGWZone>& zones, JSONObj *o)
2385{
2386 RGWZone z;
2387 z.decode_json(o);
2388 zones[z.id] = z;
2389}
2390
2391static void decode_placement_targets(map<string, RGWZoneGroupPlacementTarget>& targets, JSONObj *o)
2392{
2393 RGWZoneGroupPlacementTarget t;
2394 t.decode_json(o);
2395 targets[t.name] = t;
2396}
2397
2398static void decode_zonegroups(map<string, RGWZoneGroup>& zonegroups, JSONObj *o)
2399{
2400 RGWZoneGroup zg;
2401 zg.decode_json(o);
2402 zonegroups[zg.get_id()] = zg;
2403}
2404
2405void RGWZoneGroup::decode_json(JSONObj *obj)
2406{
2407 RGWSystemMetaObj::decode_json(obj);
2408 if (id.empty()) {
2409 derr << "old format " << dendl;
2410 JSONDecoder::decode_json("name", name, obj);
2411 id = name;
2412 }
2413 JSONDecoder::decode_json("api_name", api_name, obj);
2414 JSONDecoder::decode_json("is_master", is_master, obj);
2415 JSONDecoder::decode_json("endpoints", endpoints, obj);
2416 JSONDecoder::decode_json("hostnames", hostnames, obj);
2417 JSONDecoder::decode_json("hostnames_s3website", hostnames_s3website, obj);
2418 JSONDecoder::decode_json("master_zone", master_zone, obj);
2419 JSONDecoder::decode_json("zones", zones, decode_zones, obj);
2420 JSONDecoder::decode_json("placement_targets", placement_targets, decode_placement_targets, obj);
1d09f67e
TL
2421 string pr;
2422 JSONDecoder::decode_json("default_placement", pr, obj);
2423 default_placement.from_str(pr);
20effc67
TL
2424 JSONDecoder::decode_json("realm_id", realm_id, obj);
2425 JSONDecoder::decode_json("sync_policy", sync_policy, obj);
2426}
2427
2428void rgw_meta_sync_info::generate_test_instances(list<rgw_meta_sync_info*>& o)
2429{
2430 auto info = new rgw_meta_sync_info;
2431 info->state = rgw_meta_sync_info::StateBuildingFullSyncMaps;
2432 info->period = "periodid";
2433 info->realm_epoch = 5;
2434 o.push_back(info);
2435 o.push_back(new rgw_meta_sync_info);
2436}
2437
2438void rgw_meta_sync_marker::generate_test_instances(list<rgw_meta_sync_marker*>& o)
2439{
2440 auto marker = new rgw_meta_sync_marker;
2441 marker->state = rgw_meta_sync_marker::IncrementalSync;
2442 marker->marker = "01234";
2443 marker->realm_epoch = 5;
2444 o.push_back(marker);
2445 o.push_back(new rgw_meta_sync_marker);
2446}
2447
2448void rgw_meta_sync_status::generate_test_instances(list<rgw_meta_sync_status*>& o)
2449{
2450 o.push_back(new rgw_meta_sync_status);
2451}
2452
2453void RGWZoneParams::generate_test_instances(list<RGWZoneParams*> &o)
2454{
2455 o.push_back(new RGWZoneParams);
2456 o.push_back(new RGWZoneParams);
2457}
2458
2459void RGWPeriodLatestEpochInfo::generate_test_instances(list<RGWPeriodLatestEpochInfo*> &o)
2460{
2461 RGWPeriodLatestEpochInfo *z = new RGWPeriodLatestEpochInfo;
2462 o.push_back(z);
2463 o.push_back(new RGWPeriodLatestEpochInfo);
2464}
2465
2466void RGWRealm::generate_test_instances(list<RGWRealm*> &o)
2467{
2468 RGWRealm *z = new RGWRealm;
2469 o.push_back(z);
2470 o.push_back(new RGWRealm);
2471}
2472
2473void RGWRealm::dump(Formatter *f) const
2474{
2475 RGWSystemMetaObj::dump(f);
2476 encode_json("current_period", current_period, f);
2477 encode_json("epoch", epoch, f);
2478}
2479
2480
2481void RGWRealm::decode_json(JSONObj *obj)
2482{
2483 RGWSystemMetaObj::decode_json(obj);
2484 JSONDecoder::decode_json("current_period", current_period, obj);
2485 JSONDecoder::decode_json("epoch", epoch, obj);
2486}
2487
2488void RGWZoneGroup::generate_test_instances(list<RGWZoneGroup*>& o)
2489{
2490 RGWZoneGroup *r = new RGWZoneGroup;
2491 o.push_back(r);
2492 o.push_back(new RGWZoneGroup);
2493}
2494
2495void RGWZone::generate_test_instances(list<RGWZone*> &o)
2496{
2497 RGWZone *z = new RGWZone;
2498 o.push_back(z);
2499 o.push_back(new RGWZone);
2500}
2501
2502void RGWPeriod::generate_test_instances(list<RGWPeriod*> &o)
2503{
2504 RGWPeriod *z = new RGWPeriod;
2505 o.push_back(z);
2506 o.push_back(new RGWPeriod);
2507}
2508
2509void RGWPeriodLatestEpochInfo::dump(Formatter *f) const {
2510 encode_json("latest_epoch", epoch, f);
2511}
2512
2513void RGWPeriodLatestEpochInfo::decode_json(JSONObj *obj) {
2514 JSONDecoder::decode_json("latest_epoch", epoch, obj);
2515}
2516
2517void RGWPeriod::dump(Formatter *f) const
2518{
2519 encode_json("id", id, f);
2520 encode_json("epoch", epoch , f);
2521 encode_json("predecessor_uuid", predecessor_uuid, f);
2522 encode_json("sync_status", sync_status, f);
2523 encode_json("period_map", period_map, f);
2524 encode_json("master_zonegroup", master_zonegroup, f);
2525 encode_json("master_zone", master_zone, f);
2526 encode_json("period_config", period_config, f);
2527 encode_json("realm_id", realm_id, f);
2528 encode_json("realm_name", realm_name, f);
2529 encode_json("realm_epoch", realm_epoch, f);
2530}
2531
2532void RGWPeriod::decode_json(JSONObj *obj)
2533{
2534 JSONDecoder::decode_json("id", id, obj);
2535 JSONDecoder::decode_json("epoch", epoch, obj);
2536 JSONDecoder::decode_json("predecessor_uuid", predecessor_uuid, obj);
2537 JSONDecoder::decode_json("sync_status", sync_status, obj);
2538 JSONDecoder::decode_json("period_map", period_map, obj);
2539 JSONDecoder::decode_json("master_zonegroup", master_zonegroup, obj);
2540 JSONDecoder::decode_json("master_zone", master_zone, obj);
2541 JSONDecoder::decode_json("period_config", period_config, obj);
2542 JSONDecoder::decode_json("realm_id", realm_id, obj);
2543 JSONDecoder::decode_json("realm_name", realm_name, obj);
2544 JSONDecoder::decode_json("realm_epoch", realm_epoch, obj);
2545}
2546
2547void RGWNameToId::dump(Formatter *f) const {
2548 encode_json("obj_id", obj_id, f);
2549}
2550
2551void RGWNameToId::decode_json(JSONObj *obj) {
2552 JSONDecoder::decode_json("obj_id", obj_id, obj);
2553}
2554
2555void RGWSystemMetaObj::dump(Formatter *f) const
2556{
2557 encode_json("id", id , f);
2558 encode_json("name", name , f);
2559}
2560
2561void RGWSystemMetaObj::decode_json(JSONObj *obj)
2562{
2563 JSONDecoder::decode_json("id", id, obj);
2564 JSONDecoder::decode_json("name", name, obj);
2565}
2566
2567void RGWZoneStorageClass::dump(Formatter *f) const
2568{
2569 if (data_pool) {
2570 encode_json("data_pool", data_pool.get(), f);
2571 }
2572 if (compression_type) {
2573 encode_json("compression_type", compression_type.get(), f);
2574 }
2575}
2576
2577void RGWZoneStorageClass::decode_json(JSONObj *obj)
2578{
2579 JSONDecoder::decode_json("data_pool", data_pool, obj);
2580 JSONDecoder::decode_json("compression_type", compression_type, obj);
2581}
2582
2583void RGWZoneStorageClasses::dump(Formatter *f) const
2584{
2585 for (auto& i : m) {
2586 encode_json(i.first.c_str(), i.second, f);
2587 }
2588}
2589
2590void RGWZoneStorageClasses::decode_json(JSONObj *obj)
2591{
2592 JSONFormattable f;
2593 decode_json_obj(f, obj);
2594
2595 for (auto& field : f.object()) {
2596 JSONObj *field_obj = obj->find_obj(field.first);
2597 assert(field_obj);
2598
2599 decode_json_obj(m[field.first], field_obj);
2600 }
2601 standard_class = &m[RGW_STORAGE_CLASS_STANDARD];
2602}
2603
2604void RGWZonePlacementInfo::dump(Formatter *f) const
2605{
2606 encode_json("index_pool", index_pool, f);
2607 encode_json("storage_classes", storage_classes, f);
2608 encode_json("data_extra_pool", data_extra_pool, f);
2609 encode_json("index_type", (uint32_t)index_type, f);
39ae355f 2610 encode_json("inline_data", inline_data, f);
20effc67
TL
2611
2612 /* no real need for backward compatibility of compression_type and data_pool in here,
2613 * rather not clutter the output */
2614}
2615
2616void RGWZonePlacementInfo::decode_json(JSONObj *obj)
2617{
2618 JSONDecoder::decode_json("index_pool", index_pool, obj);
2619 JSONDecoder::decode_json("storage_classes", storage_classes, obj);
2620 JSONDecoder::decode_json("data_extra_pool", data_extra_pool, obj);
2621 uint32_t it;
2622 JSONDecoder::decode_json("index_type", it, obj);
39ae355f 2623 JSONDecoder::decode_json("inline_data", inline_data, obj);
20effc67
TL
2624 index_type = (rgw::BucketIndexType)it;
2625
2626 /* backward compatibility, these are now defined in storage_classes */
2627 string standard_compression_type;
2628 string *pcompression = nullptr;
2629 if (JSONDecoder::decode_json("compression", standard_compression_type, obj)) {
2630 pcompression = &standard_compression_type;
2631 }
2632 rgw_pool standard_data_pool;
2633 rgw_pool *ppool = nullptr;
2634 if (JSONDecoder::decode_json("data_pool", standard_data_pool, obj)) {
2635 ppool = &standard_data_pool;
2636 }
2637 if (ppool || pcompression) {
2638 storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, ppool, pcompression);
2639 }
2640}
2641
2642void RGWZoneParams::decode_json(JSONObj *obj)
2643{
2644 RGWSystemMetaObj::decode_json(obj);
2645 JSONDecoder::decode_json("domain_root", domain_root, obj);
2646 JSONDecoder::decode_json("control_pool", control_pool, obj);
2647 JSONDecoder::decode_json("gc_pool", gc_pool, obj);
2648 JSONDecoder::decode_json("lc_pool", lc_pool, obj);
2649 JSONDecoder::decode_json("log_pool", log_pool, obj);
2650 JSONDecoder::decode_json("intent_log_pool", intent_log_pool, obj);
2651 JSONDecoder::decode_json("roles_pool", roles_pool, obj);
2652 JSONDecoder::decode_json("reshard_pool", reshard_pool, obj);
2653 JSONDecoder::decode_json("usage_log_pool", usage_log_pool, obj);
2654 JSONDecoder::decode_json("user_keys_pool", user_keys_pool, obj);
2655 JSONDecoder::decode_json("user_email_pool", user_email_pool, obj);
2656 JSONDecoder::decode_json("user_swift_pool", user_swift_pool, obj);
2657 JSONDecoder::decode_json("user_uid_pool", user_uid_pool, obj);
2658 JSONDecoder::decode_json("otp_pool", otp_pool, obj);
2659 JSONDecoder::decode_json("system_key", system_key, obj);
2660 JSONDecoder::decode_json("placement_pools", placement_pools, obj);
2661 JSONDecoder::decode_json("tier_config", tier_config, obj);
2662 JSONDecoder::decode_json("realm_id", realm_id, obj);
2663 JSONDecoder::decode_json("notif_pool", notif_pool, obj);
2664
2665}
2666
2667void RGWZone::dump(Formatter *f) const
2668{
2669 encode_json("id", id, f);
2670 encode_json("name", name, f);
2671 encode_json("endpoints", endpoints, f);
2672 encode_json("log_meta", log_meta, f);
2673 encode_json("log_data", log_data, f);
2674 encode_json("bucket_index_max_shards", bucket_index_max_shards, f);
2675 encode_json("read_only", read_only, f);
2676 encode_json("tier_type", tier_type, f);
2677 encode_json("sync_from_all", sync_from_all, f);
2678 encode_json("sync_from", sync_from, f);
2679 encode_json("redirect_zone", redirect_zone, f);
2680}
2681
2682void RGWZone::decode_json(JSONObj *obj)
2683{
2684 JSONDecoder::decode_json("id", id, obj);
2685 JSONDecoder::decode_json("name", name, obj);
2686 if (id.empty()) {
2687 id = name;
2688 }
2689 JSONDecoder::decode_json("endpoints", endpoints, obj);
2690 JSONDecoder::decode_json("log_meta", log_meta, obj);
2691 JSONDecoder::decode_json("log_data", log_data, obj);
2692 JSONDecoder::decode_json("bucket_index_max_shards", bucket_index_max_shards, obj);
2693 JSONDecoder::decode_json("read_only", read_only, obj);
2694 JSONDecoder::decode_json("tier_type", tier_type, obj);
2695 JSONDecoder::decode_json("sync_from_all", sync_from_all, true, obj);
2696 JSONDecoder::decode_json("sync_from", sync_from, obj);
2697 JSONDecoder::decode_json("redirect_zone", redirect_zone, obj);
2698}
2699
2700void RGWTierACLMapping::dump(Formatter *f) const
2701{
2702 string s;
2703 switch (type) {
2704 case ACL_TYPE_EMAIL_USER:
2705 s = "email";
2706 break;
2707 case ACL_TYPE_GROUP:
2708 s = "uri";
2709 break;
2710 default:
2711 s = "id";
2712 break;
2713 }
2714 encode_json("type", s, f);
2715 encode_json("source_id", source_id, f);
2716 encode_json("dest_id", dest_id, f);
2717}
2718
2719void RGWTierACLMapping::decode_json(JSONObj *obj)
2720{
2721 string s;
2722 JSONDecoder::decode_json("type", s, obj);
2723 if (s == "email") {
2724 type = ACL_TYPE_EMAIL_USER;
2725 } else if (s == "uri") {
2726 type = ACL_TYPE_GROUP;
2727 } else {
2728 type = ACL_TYPE_CANON_USER;
2729 }
2730
2731 JSONDecoder::decode_json("source_id", source_id, obj);
2732 JSONDecoder::decode_json("dest_id", dest_id, obj);
2733}
2734
2735void RGWPeriodMap::dump(Formatter *f) const
2736{
2737 encode_json("id", id, f);
2738 encode_json_map("zonegroups", zonegroups, f);
2739 encode_json("short_zone_ids", short_zone_ids, f);
2740}
2741
2742void RGWPeriodMap::decode_json(JSONObj *obj)
2743{
2744 JSONDecoder::decode_json("id", id, obj);
2745 JSONDecoder::decode_json("zonegroups", zonegroups, decode_zonegroups, obj);
2746 /* backward compatability with region */
2747 if (zonegroups.empty()) {
2748 JSONDecoder::decode_json("regions", zonegroups, obj);
2749 }
2750 /* backward compatability with region */
2751 if (master_zonegroup.empty()) {
2752 JSONDecoder::decode_json("master_region", master_zonegroup, obj);
2753 }
2754 JSONDecoder::decode_json("short_zone_ids", short_zone_ids, obj);
2755}
2756
2757void RGWPeriodConfig::dump(Formatter *f) const
2758{
2759 encode_json("bucket_quota", bucket_quota, f);
2760 encode_json("user_quota", user_quota, f);
2761 encode_json("user_ratelimit", user_ratelimit, f);
2762 encode_json("bucket_ratelimit", bucket_ratelimit, f);
2763 encode_json("anonymous_ratelimit", anon_ratelimit, f);
2764}
2765
2766void RGWPeriodConfig::decode_json(JSONObj *obj)
2767{
2768 JSONDecoder::decode_json("bucket_quota", bucket_quota, obj);
2769 JSONDecoder::decode_json("user_quota", user_quota, obj);
2770 JSONDecoder::decode_json("user_ratelimit", user_ratelimit, obj);
2771 JSONDecoder::decode_json("bucket_ratelimit", bucket_ratelimit, obj);
2772 JSONDecoder::decode_json("anonymous_ratelimit", anon_ratelimit, obj);
2773}
2774
2775void RGWRegionMap::dump(Formatter *f) const
2776{
2777 encode_json("regions", regions, f);
2778 encode_json("master_region", master_region, f);
2779 encode_json("bucket_quota", bucket_quota, f);
2780 encode_json("user_quota", user_quota, f);
2781}
2782
2783void RGWRegionMap::decode_json(JSONObj *obj)
2784{
2785 JSONDecoder::decode_json("regions", regions, obj);
2786 JSONDecoder::decode_json("master_region", master_region, obj);
2787 JSONDecoder::decode_json("bucket_quota", bucket_quota, obj);
2788 JSONDecoder::decode_json("user_quota", user_quota, obj);
2789}
2790
2791void RGWZoneGroupMap::dump(Formatter *f) const
2792{
2793 encode_json("zonegroups", zonegroups, f);
2794 encode_json("master_zonegroup", master_zonegroup, f);
2795 encode_json("bucket_quota", bucket_quota, f);
2796 encode_json("user_quota", user_quota, f);
2797}
2798
2799void RGWZoneGroupMap::decode_json(JSONObj *obj)
2800{
2801 JSONDecoder::decode_json("zonegroups", zonegroups, obj);
2802 /* backward compatability with region */
2803 if (zonegroups.empty()) {
2804 JSONDecoder::decode_json("regions", zonegroups, obj);
2805 }
2806 JSONDecoder::decode_json("master_zonegroup", master_zonegroup, obj);
2807 /* backward compatability with region */
2808 if (master_zonegroup.empty()) {
2809 JSONDecoder::decode_json("master_region", master_zonegroup, obj);
2810 }
2811
2812 JSONDecoder::decode_json("bucket_quota", bucket_quota, obj);
2813 JSONDecoder::decode_json("user_quota", user_quota, obj);
2814}
11fdf7f2 2815