]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_zone.cc
import ceph pacific 16.2.5
[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
14#define dout_subsys ceph_subsys_rgw
15
16namespace rgw_zone_defaults {
17
18std::string zone_info_oid_prefix = "zone_info.";
19std::string zone_names_oid_prefix = "zone_names.";
20std::string region_info_oid_prefix = "region_info.";
21std::string realm_names_oid_prefix = "realms_names.";
22std::string zone_group_info_oid_prefix = "zonegroup_info.";
23std::string realm_info_oid_prefix = "realms.";
24std::string default_region_info_oid = "default.region";
25std::string default_zone_group_info_oid = "default.zonegroup";
26std::string period_info_oid_prefix = "periods.";
27std::string period_latest_epoch_info_oid = ".latest_epoch";
28std::string region_map_oid = "region_map";
29std::string default_realm_info_oid = "default.realm";
30std::string default_zonegroup_name = "default";
31std::string default_zone_name = "default";
32std::string zonegroup_names_oid_prefix = "zonegroups_names.";
33std::string RGW_DEFAULT_ZONE_ROOT_POOL = "rgw.root";
34std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL = "rgw.root";
35std::string RGW_DEFAULT_REALM_ROOT_POOL = "rgw.root";
36std::string RGW_DEFAULT_PERIOD_ROOT_POOL = "rgw.root";
37std::string default_bucket_index_pool_suffix = "rgw.buckets.index";
38std::string default_storage_extra_pool_suffix = "rgw.buckets.non-ec";
39std::string avail_pools = ".pools.avail";
40std::string default_storage_pool_suffix = "rgw.buckets.data";
41
42}
43
44using namespace rgw_zone_defaults;
45
46#define FIRST_EPOCH 1
47
48void RGWDefaultZoneGroupInfo::dump(Formatter *f) const {
49 encode_json("default_zonegroup", default_zonegroup, f);
50}
51
52void RGWDefaultZoneGroupInfo::decode_json(JSONObj *obj) {
53
54 JSONDecoder::decode_json("default_zonegroup", default_zonegroup, obj);
55 /* backward compatability with region */
56 if (default_zonegroup.empty()) {
57 JSONDecoder::decode_json("default_region", default_zonegroup, obj);
58 }
59}
60
61rgw_pool RGWZoneGroup::get_pool(CephContext *cct_) const
62{
63 if (cct_->_conf->rgw_zonegroup_root_pool.empty()) {
64 return rgw_pool(RGW_DEFAULT_ZONEGROUP_ROOT_POOL);
65 }
66
67 return rgw_pool(cct_->_conf->rgw_zonegroup_root_pool);
68}
69
b3b6e05e 70int RGWZoneGroup::create_default(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2
TL
71{
72 name = default_zonegroup_name;
73 api_name = default_zonegroup_name;
74 is_master = true;
75
76 RGWZoneGroupPlacementTarget placement_target;
77 placement_target.name = "default-placement";
78 placement_targets[placement_target.name] = placement_target;
79 default_placement.name = "default-placement";
80
81 RGWZoneParams zone_params(default_zone_name);
82
b3b6e05e 83 int r = zone_params.init(dpp, cct, sysobj_svc, y, false);
11fdf7f2 84 if (r < 0) {
b3b6e05e 85 ldpp_dout(dpp, 0) << "create_default: error initializing zone params: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
86 return r;
87 }
88
b3b6e05e 89 r = zone_params.create_default(dpp, y);
11fdf7f2 90 if (r < 0 && r != -EEXIST) {
b3b6e05e 91 ldpp_dout(dpp, 0) << "create_default: error in create_default zone params: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
92 return r;
93 } else if (r == -EEXIST) {
b3b6e05e 94 ldpp_dout(dpp, 10) << "zone_params::create_default() returned -EEXIST, we raced with another default zone_params creation" << dendl;
11fdf7f2 95 zone_params.clear_id();
b3b6e05e 96 r = zone_params.init(dpp, cct, sysobj_svc, y);
11fdf7f2 97 if (r < 0) {
b3b6e05e 98 ldpp_dout(dpp, 0) << "create_default: error in init existing zone params: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
99 return r;
100 }
b3b6e05e 101 ldpp_dout(dpp, 20) << "zone_params::create_default() " << zone_params.get_name() << " id " << zone_params.get_id()
11fdf7f2
TL
102 << dendl;
103 }
104
105 RGWZone& default_zone = zones[zone_params.get_id()];
106 default_zone.name = zone_params.get_name();
107 default_zone.id = zone_params.get_id();
108 master_zone = default_zone.id;
109
b3b6e05e 110 r = create(dpp, y);
11fdf7f2 111 if (r < 0 && r != -EEXIST) {
b3b6e05e 112 ldpp_dout(dpp, 0) << "error storing zone group info: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
113 return r;
114 }
115
116 if (r == -EEXIST) {
b3b6e05e 117 ldpp_dout(dpp, 10) << "create_default() returned -EEXIST, we raced with another zonegroup creation" << dendl;
11fdf7f2 118 id.clear();
b3b6e05e 119 r = init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
120 if (r < 0) {
121 return r;
122 }
123 }
124
125 if (old_format) {
126 name = id;
127 }
128
b3b6e05e 129 post_process_params(dpp, y);
11fdf7f2
TL
130
131 return 0;
132}
133
134const string RGWZoneGroup::get_default_oid(bool old_region_format) const
135{
136 if (old_region_format) {
137 if (cct->_conf->rgw_default_region_info_oid.empty()) {
138 return default_region_info_oid;
139 }
140 return cct->_conf->rgw_default_region_info_oid;
141 }
142
143 string default_oid = cct->_conf->rgw_default_zonegroup_info_oid;
144
145 if (cct->_conf->rgw_default_zonegroup_info_oid.empty()) {
146 default_oid = default_zone_group_info_oid;
147 }
148
149 default_oid += "." + realm_id;
150
151 return default_oid;
152}
153
154const string& RGWZoneGroup::get_info_oid_prefix(bool old_region_format) const
155{
156 if (old_region_format) {
157 return region_info_oid_prefix;
158 }
159 return zone_group_info_oid_prefix;
160}
161
162const string& RGWZoneGroup::get_names_oid_prefix() const
163{
164 return zonegroup_names_oid_prefix;
165}
166
167const string& RGWZoneGroup::get_predefined_name(CephContext *cct) const {
168 return cct->_conf->rgw_zonegroup;
169}
170
171int RGWZoneGroup::equals(const string& other_zonegroup) const
172{
173 if (is_master && other_zonegroup.empty())
174 return true;
175
176 return (id == other_zonegroup);
177}
178
b3b6e05e
TL
179int RGWZoneGroup::add_zone(const DoutPrefixProvider *dpp,
180 const RGWZoneParams& zone_params, bool *is_master, bool *read_only,
11fdf7f2
TL
181 const list<string>& endpoints, const string *ptier_type,
182 bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm,
9f95a23c 183 string *predirect_zone, std::optional<int> bucket_index_max_shards,
f67539c2
TL
184 RGWSyncModulesManager *sync_mgr,
185 optional_yield y)
11fdf7f2
TL
186{
187 auto& zone_id = zone_params.get_id();
188 auto& zone_name = zone_params.get_name();
189
190 // check for duplicate zone name on insert
191 if (!zones.count(zone_id)) {
192 for (const auto& zone : zones) {
193 if (zone.second.name == zone_name) {
b3b6e05e 194 ldpp_dout(dpp, 0) << "ERROR: found existing zone name " << zone_name
11fdf7f2
TL
195 << " (" << zone.first << ") in zonegroup " << get_name() << dendl;
196 return -EEXIST;
197 }
198 }
199 }
200
201 if (is_master) {
202 if (*is_master) {
203 if (!master_zone.empty() && master_zone != zone_id) {
b3b6e05e 204 ldpp_dout(dpp, 0) << "NOTICE: overriding master zone: " << master_zone << dendl;
11fdf7f2
TL
205 }
206 master_zone = zone_id;
207 } else if (master_zone == zone_id) {
208 master_zone.clear();
209 }
210 }
211
212 RGWZone& zone = zones[zone_id];
213 zone.name = zone_name;
214 zone.id = zone_id;
215 if (!endpoints.empty()) {
216 zone.endpoints = endpoints;
217 }
218 if (read_only) {
219 zone.read_only = *read_only;
220 }
221 if (ptier_type) {
222 zone.tier_type = *ptier_type;
223 if (!sync_mgr->get_module(*ptier_type, nullptr)) {
b3b6e05e 224 ldpp_dout(dpp, 0) << "ERROR: could not found sync module: " << *ptier_type
11fdf7f2
TL
225 << ", valid sync modules: "
226 << sync_mgr->get_registered_module_names()
227 << dendl;
228 return -ENOENT;
229 }
230 }
231
232 if (psync_from_all) {
233 zone.sync_from_all = *psync_from_all;
234 }
235
236 if (predirect_zone) {
237 zone.redirect_zone = *predirect_zone;
238 }
239
9f95a23c
TL
240 if (bucket_index_max_shards) {
241 zone.bucket_index_max_shards = *bucket_index_max_shards;
242 }
243
11fdf7f2
TL
244 for (auto add : sync_from) {
245 zone.sync_from.insert(add);
246 }
247
248 for (auto rm : sync_from_rm) {
249 zone.sync_from.erase(rm);
250 }
251
b3b6e05e 252 post_process_params(dpp, y);
11fdf7f2 253
b3b6e05e 254 return update(dpp,y);
11fdf7f2
TL
255}
256
257
b3b6e05e
TL
258int RGWZoneGroup::rename_zone(const DoutPrefixProvider *dpp,
259 const RGWZoneParams& zone_params,
f67539c2
TL
260 optional_yield y)
261{
11fdf7f2
TL
262 RGWZone& zone = zones[zone_params.get_id()];
263 zone.name = zone_params.get_name();
f67539c2 264
b3b6e05e 265 return update(dpp, y);
11fdf7f2
TL
266}
267
b3b6e05e 268void RGWZoneGroup::post_process_params(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
269{
270 bool log_data = zones.size() > 1;
271
272 if (master_zone.empty()) {
9f95a23c 273 auto iter = zones.begin();
11fdf7f2
TL
274 if (iter != zones.end()) {
275 master_zone = iter->first;
276 }
277 }
278
9f95a23c
TL
279 for (auto& item : zones) {
280 RGWZone& zone = item.second;
11fdf7f2
TL
281 zone.log_data = log_data;
282
283 RGWZoneParams zone_params(zone.id, zone.name);
b3b6e05e 284 int ret = zone_params.init(dpp, cct, sysobj_svc, y);
11fdf7f2 285 if (ret < 0) {
b3b6e05e 286 ldpp_dout(dpp, 0) << "WARNING: could not read zone params for zone id=" << zone.id << " name=" << zone.name << dendl;
11fdf7f2
TL
287 continue;
288 }
289
9f95a23c
TL
290 for (auto& pitem : zone_params.placement_pools) {
291 const string& placement_name = pitem.first;
11fdf7f2
TL
292 if (placement_targets.find(placement_name) == placement_targets.end()) {
293 RGWZoneGroupPlacementTarget placement_target;
294 placement_target.name = placement_name;
295 placement_targets[placement_name] = placement_target;
296 }
297 }
298 }
299
300 if (default_placement.empty() && !placement_targets.empty()) {
301 default_placement.init(placement_targets.begin()->first, RGW_STORAGE_CLASS_STANDARD);
302 }
303}
304
b3b6e05e 305int RGWZoneGroup::remove_zone(const DoutPrefixProvider *dpp, const std::string& zone_id, optional_yield y)
11fdf7f2 306{
9f95a23c 307 auto iter = zones.find(zone_id);
11fdf7f2 308 if (iter == zones.end()) {
b3b6e05e 309 ldpp_dout(dpp, 0) << "zone id " << zone_id << " is not a part of zonegroup "
11fdf7f2
TL
310 << name << dendl;
311 return -ENOENT;
312 }
313
314 zones.erase(iter);
315
b3b6e05e 316 post_process_params(dpp, y);
11fdf7f2 317
b3b6e05e 318 return update(dpp, y);
11fdf7f2
TL
319}
320
b3b6e05e 321int RGWZoneGroup::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
f67539c2 322 bool old_format)
11fdf7f2
TL
323{
324 if (realm_id.empty()) {
325 /* try using default realm */
326 RGWRealm realm;
b3b6e05e 327 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
328 // no default realm exist
329 if (ret < 0) {
b3b6e05e 330 return read_id(dpp, default_zonegroup_name, default_id, y);
11fdf7f2
TL
331 }
332 realm_id = realm.get_id();
333 }
334
b3b6e05e 335 return RGWSystemMetaObj::read_default_id(dpp, default_id, y, old_format);
11fdf7f2
TL
336}
337
b3b6e05e 338int RGWZoneGroup::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
339{
340 if (realm_id.empty()) {
341 /* try using default realm */
342 RGWRealm realm;
b3b6e05e 343 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2 344 if (ret < 0) {
b3b6e05e 345 ldpp_dout(dpp, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
346 return -EINVAL;
347 }
348 realm_id = realm.get_id();
349 }
350
b3b6e05e 351 return RGWSystemMetaObj::set_as_default(dpp, y, exclusive);
11fdf7f2
TL
352}
353
354void RGWSystemMetaObj::reinit_instance(CephContext *_cct, RGWSI_SysObj *_sysobj_svc)
355{
356 cct = _cct;
357 sysobj_svc = _sysobj_svc;
358 zone_svc = _sysobj_svc->get_zone_svc();
359}
360
b3b6e05e 361int RGWSystemMetaObj::init(const DoutPrefixProvider *dpp, CephContext *_cct, RGWSI_SysObj *_sysobj_svc,
f67539c2
TL
362 optional_yield y,
363 bool setup_obj, bool old_format)
11fdf7f2
TL
364{
365 reinit_instance(_cct, _sysobj_svc);
366
367 if (!setup_obj)
368 return 0;
369
370 if (old_format && id.empty()) {
371 id = name;
372 }
373
374 if (id.empty()) {
375 int r;
376 if (name.empty()) {
377 name = get_predefined_name(cct);
378 }
379 if (name.empty()) {
b3b6e05e 380 r = use_default(dpp, y, old_format);
11fdf7f2
TL
381 if (r < 0) {
382 return r;
383 }
384 } else if (!old_format) {
b3b6e05e 385 r = read_id(dpp, name, id, y);
11fdf7f2
TL
386 if (r < 0) {
387 if (r != -ENOENT) {
b3b6e05e 388 ldpp_dout(dpp, 0) << "error in read_id for object name: " << name << " : " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
389 }
390 return r;
391 }
392 }
393 }
394
b3b6e05e 395 return read_info(dpp, id, y, old_format);
11fdf7f2
TL
396}
397
b3b6e05e
TL
398int RGWSystemMetaObj::read_default(const DoutPrefixProvider *dpp,
399 RGWDefaultSystemMetaObjInfo& default_info,
f67539c2 400 const string& oid, optional_yield y)
11fdf7f2
TL
401{
402 using ceph::decode;
403 auto pool = get_pool(cct);
404 bufferlist bl;
405
406 auto obj_ctx = sysobj_svc->init_obj_ctx();
407 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
b3b6e05e 408 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2
TL
409 if (ret < 0)
410 return ret;
411
412 try {
413 auto iter = bl.cbegin();
414 decode(default_info, iter);
415 } catch (buffer::error& err) {
b3b6e05e 416 ldpp_dout(dpp, 0) << "error decoding data from " << pool << ":" << oid << dendl;
11fdf7f2
TL
417 return -EIO;
418 }
419
420 return 0;
421}
422
b3b6e05e 423int RGWSystemMetaObj::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
f67539c2 424 bool old_format)
11fdf7f2
TL
425{
426 RGWDefaultSystemMetaObjInfo default_info;
427
b3b6e05e 428 int ret = read_default(dpp, default_info, get_default_oid(old_format), y);
11fdf7f2
TL
429 if (ret < 0) {
430 return ret;
431 }
432
433 default_id = default_info.default_id;
434
435 return 0;
436}
437
b3b6e05e 438int RGWSystemMetaObj::use_default(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2 439{
b3b6e05e 440 return read_default_id(dpp, id, y, old_format);
11fdf7f2
TL
441}
442
b3b6e05e 443int RGWSystemMetaObj::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
444{
445 using ceph::encode;
446 string oid = get_default_oid();
447
448 rgw_pool pool(get_pool(cct));
449 bufferlist bl;
450
451 RGWDefaultSystemMetaObjInfo default_info;
452 default_info.default_id = id;
453
454 encode(default_info, bl);
455
456 auto obj_ctx = sysobj_svc->init_obj_ctx();
457 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
458 int ret = sysobj.wop()
459 .set_exclusive(exclusive)
b3b6e05e 460 .write(dpp, bl, y);
11fdf7f2
TL
461 if (ret < 0)
462 return ret;
463
464 return 0;
465}
466
b3b6e05e 467int RGWSystemMetaObj::read_id(const DoutPrefixProvider *dpp, const string& obj_name, string& object_id,
f67539c2 468 optional_yield y)
11fdf7f2
TL
469{
470 using ceph::decode;
471 rgw_pool pool(get_pool(cct));
472 bufferlist bl;
473
474 string oid = get_names_oid_prefix() + obj_name;
475
476 auto obj_ctx = sysobj_svc->init_obj_ctx();
477 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
b3b6e05e 478 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2
TL
479 if (ret < 0) {
480 return ret;
481 }
482
483 RGWNameToId nameToId;
484 try {
485 auto iter = bl.cbegin();
486 decode(nameToId, iter);
487 } catch (buffer::error& err) {
b3b6e05e 488 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
11fdf7f2
TL
489 return -EIO;
490 }
491 object_id = nameToId.obj_id;
492 return 0;
493}
494
b3b6e05e 495int RGWSystemMetaObj::delete_obj(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2
TL
496{
497 rgw_pool pool(get_pool(cct));
498
499 auto obj_ctx = sysobj_svc->init_obj_ctx();
500
501 /* check to see if obj is the default */
502 RGWDefaultSystemMetaObjInfo default_info;
b3b6e05e 503 int ret = read_default(dpp, default_info, get_default_oid(old_format), y);
11fdf7f2
TL
504 if (ret < 0 && ret != -ENOENT)
505 return ret;
506 if (default_info.default_id == id || (old_format && default_info.default_id == name)) {
507 string oid = get_default_oid(old_format);
508 rgw_raw_obj default_named_obj(pool, oid);
509 auto sysobj = sysobj_svc->get_obj(obj_ctx, default_named_obj);
b3b6e05e 510 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 511 if (ret < 0) {
b3b6e05e 512 ldpp_dout(dpp, 0) << "Error delete default obj name " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
513 return ret;
514 }
515 }
516 if (!old_format) {
517 string oid = get_names_oid_prefix() + name;
518 rgw_raw_obj object_name(pool, oid);
519 auto sysobj = sysobj_svc->get_obj(obj_ctx, object_name);
b3b6e05e 520 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 521 if (ret < 0) {
b3b6e05e 522 ldpp_dout(dpp, 0) << "Error delete obj name " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
523 return ret;
524 }
525 }
526
527 string oid = get_info_oid_prefix(old_format);
528 if (old_format) {
529 oid += name;
530 } else {
531 oid += id;
532 }
533
534 rgw_raw_obj object_id(pool, oid);
535 auto sysobj = sysobj_svc->get_obj(obj_ctx, object_id);
b3b6e05e 536 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 537 if (ret < 0) {
b3b6e05e 538 ldpp_dout(dpp, 0) << "Error delete object id " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
539 }
540
541 return ret;
542}
543
b3b6e05e 544int RGWSystemMetaObj::store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
545{
546 rgw_pool pool(get_pool(cct));
547 string oid = get_names_oid_prefix() + name;
548
549 RGWNameToId nameToId;
550 nameToId.obj_id = id;
551
552 bufferlist bl;
553 using ceph::encode;
554 encode(nameToId, bl);
555 auto obj_ctx = sysobj_svc->init_obj_ctx();
556 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
557 return sysobj.wop()
558 .set_exclusive(exclusive)
b3b6e05e 559 .write(dpp, bl, y);
11fdf7f2
TL
560}
561
b3b6e05e 562int RGWSystemMetaObj::rename(const DoutPrefixProvider *dpp, const string& new_name, optional_yield y)
11fdf7f2
TL
563{
564 string new_id;
b3b6e05e 565 int ret = read_id(dpp, new_name, new_id, y);
11fdf7f2
TL
566 if (!ret) {
567 return -EEXIST;
568 }
569 if (ret < 0 && ret != -ENOENT) {
b3b6e05e 570 ldpp_dout(dpp, 0) << "Error read_id " << new_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
571 return ret;
572 }
573 string old_name = name;
574 name = new_name;
b3b6e05e 575 ret = update(dpp, y);
11fdf7f2 576 if (ret < 0) {
b3b6e05e 577 ldpp_dout(dpp, 0) << "Error storing new obj info " << new_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
578 return ret;
579 }
b3b6e05e 580 ret = store_name(dpp, true, y);
11fdf7f2 581 if (ret < 0) {
b3b6e05e 582 ldpp_dout(dpp, 0) << "Error storing new name " << new_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
583 return ret;
584 }
585 /* delete old name */
586 rgw_pool pool(get_pool(cct));
587 string oid = get_names_oid_prefix() + old_name;
588 rgw_raw_obj old_name_obj(pool, oid);
589 auto obj_ctx = sysobj_svc->init_obj_ctx();
590 auto sysobj = sysobj_svc->get_obj(obj_ctx, old_name_obj);
b3b6e05e 591 ret = sysobj.wop().remove(dpp, y);
11fdf7f2 592 if (ret < 0) {
b3b6e05e 593 ldpp_dout(dpp, 0) << "Error delete old obj name " << old_name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
594 return ret;
595 }
596
597 return ret;
598}
599
b3b6e05e 600int RGWSystemMetaObj::read_info(const DoutPrefixProvider *dpp, const string& obj_id, optional_yield y,
f67539c2 601 bool old_format)
11fdf7f2
TL
602{
603 rgw_pool pool(get_pool(cct));
604
605 bufferlist bl;
606
607 string oid = get_info_oid_prefix(old_format) + obj_id;
608
609 auto obj_ctx = sysobj_svc->init_obj_ctx();
610 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
b3b6e05e 611 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2 612 if (ret < 0) {
b3b6e05e 613 ldpp_dout(dpp, 0) << "failed reading obj info from " << pool << ":" << oid << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
614 return ret;
615 }
616 using ceph::decode;
617
618 try {
619 auto iter = bl.cbegin();
620 decode(*this, iter);
621 } catch (buffer::error& err) {
b3b6e05e 622 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
11fdf7f2
TL
623 return -EIO;
624 }
625
626 return 0;
627}
628
b3b6e05e 629int RGWSystemMetaObj::read(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2 630{
b3b6e05e 631 int ret = read_id(dpp, name, id, y);
11fdf7f2
TL
632 if (ret < 0) {
633 return ret;
634 }
635
b3b6e05e 636 return read_info(dpp, id, y);
11fdf7f2
TL
637}
638
b3b6e05e 639int RGWSystemMetaObj::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
640{
641 int ret;
f67539c2 642
11fdf7f2 643 /* check to see the name is not used */
b3b6e05e 644 ret = read_id(dpp, name, id, y);
11fdf7f2 645 if (exclusive && ret == 0) {
b3b6e05e 646 ldpp_dout(dpp, 10) << "ERROR: name " << name << " already in use for obj id " << id << dendl;
11fdf7f2
TL
647 return -EEXIST;
648 } else if ( ret < 0 && ret != -ENOENT) {
b3b6e05e 649 ldpp_dout(dpp, 0) << "failed reading obj id " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
650 return ret;
651 }
652
653 if (id.empty()) {
654 /* create unique id */
655 uuid_d new_uuid;
656 char uuid_str[37];
657 new_uuid.generate_random();
658 new_uuid.print(uuid_str);
659 id = uuid_str;
660 }
661
b3b6e05e 662 ret = store_info(dpp, exclusive, y);
11fdf7f2 663 if (ret < 0) {
b3b6e05e 664 ldpp_dout(dpp, 0) << "ERROR: storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
665 return ret;
666 }
667
b3b6e05e 668 return store_name(dpp, exclusive, y);
11fdf7f2
TL
669}
670
b3b6e05e 671int RGWSystemMetaObj::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
672{
673 rgw_pool pool(get_pool(cct));
674
675 string oid = get_info_oid_prefix() + id;
676
677 bufferlist bl;
678 using ceph::encode;
679 encode(*this, bl);
680 auto obj_ctx = sysobj_svc->init_obj_ctx();
681 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
682 return sysobj.wop()
683 .set_exclusive(exclusive)
b3b6e05e 684 .write(dpp, bl, y);
11fdf7f2
TL
685}
686
b3b6e05e 687int RGWSystemMetaObj::write(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2 688{
b3b6e05e 689 int ret = store_info(dpp, exclusive, y);
11fdf7f2 690 if (ret < 0) {
b3b6e05e 691 ldpp_dout(dpp, 20) << __func__ << "(): store_info() returned ret=" << ret << dendl;
11fdf7f2
TL
692 return ret;
693 }
b3b6e05e 694 ret = store_name(dpp, exclusive, y);
11fdf7f2 695 if (ret < 0) {
b3b6e05e 696 ldpp_dout(dpp, 20) << __func__ << "(): store_name() returned ret=" << ret << dendl;
11fdf7f2
TL
697 return ret;
698 }
699 return 0;
700}
701
702
703const string& RGWRealm::get_predefined_name(CephContext *cct) const {
704 return cct->_conf->rgw_realm;
705}
706
b3b6e05e 707int RGWRealm::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2 708{
b3b6e05e 709 int ret = RGWSystemMetaObj::create(dpp, y, exclusive);
11fdf7f2 710 if (ret < 0) {
b3b6e05e 711 ldpp_dout(dpp, 0) << "ERROR creating new realm object " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
712 return ret;
713 }
714 // create the control object for watch/notify
b3b6e05e 715 ret = create_control(dpp, exclusive, y);
11fdf7f2 716 if (ret < 0) {
b3b6e05e 717 ldpp_dout(dpp, 0) << "ERROR creating control for new realm " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
718 return ret;
719 }
720 RGWPeriod period;
721 if (current_period.empty()) {
722 /* create new period for the realm */
b3b6e05e 723 ret = period.init(dpp, cct, sysobj_svc, id, y, name, false);
11fdf7f2
TL
724 if (ret < 0 ) {
725 return ret;
726 }
b3b6e05e 727 ret = period.create(dpp, y, true);
11fdf7f2 728 if (ret < 0) {
b3b6e05e 729 ldpp_dout(dpp, 0) << "ERROR: creating new period for realm " << name << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
730 return ret;
731 }
732 } else {
733 period = RGWPeriod(current_period, 0);
b3b6e05e 734 int ret = period.init(dpp, cct, sysobj_svc, id, y, name);
11fdf7f2 735 if (ret < 0) {
b3b6e05e 736 ldpp_dout(dpp, 0) << "ERROR: failed to init period " << current_period << dendl;
11fdf7f2
TL
737 return ret;
738 }
739 }
b3b6e05e 740 ret = set_current_period(dpp, period, y);
11fdf7f2 741 if (ret < 0) {
b3b6e05e 742 ldpp_dout(dpp, 0) << "ERROR: failed set current period " << current_period << dendl;
11fdf7f2
TL
743 return ret;
744 }
745 // try to set as default. may race with another create, so pass exclusive=true
746 // so we don't override an existing default
b3b6e05e 747 ret = set_as_default(dpp, y, true);
11fdf7f2 748 if (ret < 0 && ret != -EEXIST) {
b3b6e05e 749 ldpp_dout(dpp, 0) << "WARNING: failed to set realm as default realm, ret=" << ret << dendl;
11fdf7f2
TL
750 }
751
752 return 0;
753}
754
b3b6e05e 755int RGWRealm::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2 756{
b3b6e05e 757 int ret = RGWSystemMetaObj::delete_obj(dpp, y);
11fdf7f2
TL
758 if (ret < 0) {
759 return ret;
760 }
b3b6e05e 761 return delete_control(dpp, y);
11fdf7f2
TL
762}
763
b3b6e05e 764int RGWRealm::create_control(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
765{
766 auto pool = rgw_pool{get_pool(cct)};
767 auto oid = get_control_oid();
768 bufferlist bl;
769 auto obj_ctx = sysobj_svc->init_obj_ctx();
770 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
771 return sysobj.wop()
772 .set_exclusive(exclusive)
b3b6e05e 773 .write(dpp, bl, y);
11fdf7f2
TL
774}
775
b3b6e05e 776int RGWRealm::delete_control(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
777{
778 auto pool = rgw_pool{get_pool(cct)};
779 auto obj = rgw_raw_obj{pool, get_control_oid()};
780 auto obj_ctx = sysobj_svc->init_obj_ctx();
781 auto sysobj = sysobj_svc->get_obj(obj_ctx, obj);
b3b6e05e 782 return sysobj.wop().remove(dpp, y);
11fdf7f2
TL
783}
784
785rgw_pool RGWRealm::get_pool(CephContext *cct) const
786{
787 if (cct->_conf->rgw_realm_root_pool.empty()) {
788 return rgw_pool(RGW_DEFAULT_REALM_ROOT_POOL);
789 }
790 return rgw_pool(cct->_conf->rgw_realm_root_pool);
791}
792
793const string RGWRealm::get_default_oid(bool old_format) const
794{
795 if (cct->_conf->rgw_default_realm_info_oid.empty()) {
796 return default_realm_info_oid;
797 }
798 return cct->_conf->rgw_default_realm_info_oid;
799}
800
801const string& RGWRealm::get_names_oid_prefix() const
802{
803 return realm_names_oid_prefix;
804}
805
806const string& RGWRealm::get_info_oid_prefix(bool old_format) const
807{
808 return realm_info_oid_prefix;
809}
810
b3b6e05e 811int RGWRealm::set_current_period(const DoutPrefixProvider *dpp, RGWPeriod& period, optional_yield y)
11fdf7f2
TL
812{
813 // update realm epoch to match the period's
814 if (epoch > period.get_realm_epoch()) {
b3b6e05e 815 ldpp_dout(dpp, 0) << "ERROR: set_current_period with old realm epoch "
11fdf7f2
TL
816 << period.get_realm_epoch() << ", current epoch=" << epoch << dendl;
817 return -EINVAL;
818 }
819 if (epoch == period.get_realm_epoch() && current_period != period.get_id()) {
b3b6e05e 820 ldpp_dout(dpp, 0) << "ERROR: set_current_period with same realm epoch "
11fdf7f2
TL
821 << period.get_realm_epoch() << ", but different period id "
822 << period.get_id() << " != " << current_period << dendl;
823 return -EINVAL;
824 }
825
826 epoch = period.get_realm_epoch();
827 current_period = period.get_id();
828
b3b6e05e 829 int ret = update(dpp, y);
11fdf7f2 830 if (ret < 0) {
b3b6e05e 831 ldpp_dout(dpp, 0) << "ERROR: period update: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
832 return ret;
833 }
834
b3b6e05e 835 ret = period.reflect(dpp, y);
11fdf7f2 836 if (ret < 0) {
b3b6e05e 837 ldpp_dout(dpp, 0) << "ERROR: period.reflect(): " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
838 return ret;
839 }
840
841 return 0;
842}
843
844string RGWRealm::get_control_oid() const
845{
846 return get_info_oid_prefix() + id + ".control";
847}
848
b3b6e05e 849int RGWRealm::notify_zone(const DoutPrefixProvider *dpp, bufferlist& bl, optional_yield y)
11fdf7f2
TL
850{
851 rgw_pool pool{get_pool(cct)};
852 auto obj_ctx = sysobj_svc->init_obj_ctx();
853 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, get_control_oid()});
b3b6e05e 854 int ret = sysobj.wn().notify(dpp, bl, 0, nullptr, y);
11fdf7f2
TL
855 if (ret < 0) {
856 return ret;
857 }
858 return 0;
859}
860
b3b6e05e 861int RGWRealm::notify_new_period(const DoutPrefixProvider *dpp, const RGWPeriod& period, optional_yield y)
11fdf7f2
TL
862{
863 bufferlist bl;
864 using ceph::encode;
865 // push the period to dependent zonegroups/zones
866 encode(RGWRealmNotify::ZonesNeedPeriod, bl);
867 encode(period, bl);
868 // reload the gateway with the new period
869 encode(RGWRealmNotify::Reload, bl);
870
b3b6e05e 871 return notify_zone(dpp, bl, y);
11fdf7f2
TL
872}
873
874std::string RGWPeriodConfig::get_oid(const std::string& realm_id)
875{
876 if (realm_id.empty()) {
877 return "period_config.default";
878 }
879 return "period_config." + realm_id;
880}
881
882rgw_pool RGWPeriodConfig::get_pool(CephContext *cct)
883{
884 const auto& pool_name = cct->_conf->rgw_period_root_pool;
885 if (pool_name.empty()) {
886 return {RGW_DEFAULT_PERIOD_ROOT_POOL};
887 }
888 return {pool_name};
889}
890
b3b6e05e 891int RGWPeriodConfig::read(const DoutPrefixProvider *dpp, RGWSI_SysObj *sysobj_svc, const std::string& realm_id,
f67539c2 892 optional_yield y)
11fdf7f2
TL
893{
894 const auto& pool = get_pool(sysobj_svc->ctx());
895 const auto& oid = get_oid(realm_id);
896 bufferlist bl;
897
898 auto obj_ctx = sysobj_svc->init_obj_ctx();
899 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
b3b6e05e 900 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2
TL
901 if (ret < 0) {
902 return ret;
903 }
904 using ceph::decode;
905 try {
906 auto iter = bl.cbegin();
907 decode(*this, iter);
908 } catch (buffer::error& err) {
909 return -EIO;
910 }
911 return 0;
912}
913
b3b6e05e
TL
914int RGWPeriodConfig::write(const DoutPrefixProvider *dpp,
915 RGWSI_SysObj *sysobj_svc,
f67539c2 916 const std::string& realm_id, optional_yield y)
11fdf7f2
TL
917{
918 const auto& pool = get_pool(sysobj_svc->ctx());
919 const auto& oid = get_oid(realm_id);
920 bufferlist bl;
921 using ceph::encode;
922 encode(*this, bl);
923 auto obj_ctx = sysobj_svc->init_obj_ctx();
924 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
925 return sysobj.wop()
926 .set_exclusive(false)
b3b6e05e 927 .write(dpp, bl, y);
11fdf7f2
TL
928}
929
b3b6e05e 930int RGWPeriod::init(const DoutPrefixProvider *dpp, CephContext *_cct, RGWSI_SysObj *_sysobj_svc,
f67539c2 931 const string& period_realm_id, optional_yield y,
11fdf7f2
TL
932 const string& period_realm_name, bool setup_obj)
933{
934 cct = _cct;
935 sysobj_svc = _sysobj_svc;
936
937 realm_id = period_realm_id;
938 realm_name = period_realm_name;
939
940 if (!setup_obj)
941 return 0;
942
b3b6e05e 943 return init(dpp, _cct, _sysobj_svc, y, setup_obj);
11fdf7f2
TL
944}
945
946
b3b6e05e
TL
947int RGWPeriod::init(const DoutPrefixProvider *dpp,
948 CephContext *_cct, RGWSI_SysObj *_sysobj_svc,
f67539c2 949 optional_yield y, bool setup_obj)
11fdf7f2
TL
950{
951 cct = _cct;
952 sysobj_svc = _sysobj_svc;
953
954 if (!setup_obj)
955 return 0;
956
957 if (id.empty()) {
958 RGWRealm realm(realm_id, realm_name);
b3b6e05e 959 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2 960 if (ret < 0) {
b3b6e05e 961 ldpp_dout(dpp, 0) << "RGWPeriod::init failed to init realm " << realm_name << " id " << realm_id << " : " <<
11fdf7f2
TL
962 cpp_strerror(-ret) << dendl;
963 return ret;
964 }
965 id = realm.get_current_period();
966 realm_id = realm.get_id();
967 }
968
969 if (!epoch) {
b3b6e05e 970 int ret = use_latest_epoch(dpp, y);
11fdf7f2 971 if (ret < 0) {
b3b6e05e 972 ldpp_dout(dpp, 0) << "failed to use_latest_epoch period id " << id << " realm " << realm_name << " id " << realm_id
11fdf7f2
TL
973 << " : " << cpp_strerror(-ret) << dendl;
974 return ret;
975 }
976 }
977
b3b6e05e 978 return read_info(dpp, y);
11fdf7f2
TL
979}
980
981
982int RGWPeriod::get_zonegroup(RGWZoneGroup& zonegroup,
983 const string& zonegroup_id) const
984{
985 map<string, RGWZoneGroup>::const_iterator iter;
986 if (!zonegroup_id.empty()) {
987 iter = period_map.zonegroups.find(zonegroup_id);
988 } else {
989 iter = period_map.zonegroups.find("default");
990 }
991 if (iter != period_map.zonegroups.end()) {
992 zonegroup = iter->second;
993 return 0;
994 }
995
996 return -ENOENT;
997}
998
999const string& RGWPeriod::get_latest_epoch_oid() const
1000{
1001 if (cct->_conf->rgw_period_latest_epoch_info_oid.empty()) {
1002 return period_latest_epoch_info_oid;
1003 }
1004 return cct->_conf->rgw_period_latest_epoch_info_oid;
1005}
1006
1007const string& RGWPeriod::get_info_oid_prefix() const
1008{
1009 return period_info_oid_prefix;
1010}
1011
1012const string RGWPeriod::get_period_oid_prefix() const
1013{
1014 return get_info_oid_prefix() + id;
1015}
1016
1017const string RGWPeriod::get_period_oid() const
1018{
1019 std::ostringstream oss;
1020 oss << get_period_oid_prefix();
1021 // skip the epoch for the staging period
1022 if (id != get_staging_id(realm_id))
1023 oss << "." << epoch;
1024 return oss.str();
1025}
1026
b3b6e05e
TL
1027int RGWPeriod::read_latest_epoch(const DoutPrefixProvider *dpp,
1028 RGWPeriodLatestEpochInfo& info,
f67539c2 1029 optional_yield y,
11fdf7f2
TL
1030 RGWObjVersionTracker *objv)
1031{
1032 string oid = get_period_oid_prefix() + get_latest_epoch_oid();
1033
1034 rgw_pool pool(get_pool(cct));
1035 bufferlist bl;
1036 auto obj_ctx = sysobj_svc->init_obj_ctx();
1037 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, oid});
b3b6e05e 1038 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2 1039 if (ret < 0) {
b3b6e05e 1040 ldpp_dout(dpp, 1) << "error read_lastest_epoch " << pool << ":" << oid << dendl;
11fdf7f2
TL
1041 return ret;
1042 }
1043 try {
1044 auto iter = bl.cbegin();
1045 using ceph::decode;
1046 decode(info, iter);
1047 } catch (buffer::error& err) {
b3b6e05e 1048 ldpp_dout(dpp, 0) << "error decoding data from " << pool << ":" << oid << dendl;
11fdf7f2
TL
1049 return -EIO;
1050 }
1051
1052 return 0;
1053}
1054
b3b6e05e 1055int RGWPeriod::get_latest_epoch(const DoutPrefixProvider *dpp, epoch_t& latest_epoch, optional_yield y)
11fdf7f2
TL
1056{
1057 RGWPeriodLatestEpochInfo info;
1058
b3b6e05e 1059 int ret = read_latest_epoch(dpp, info, y);
11fdf7f2
TL
1060 if (ret < 0) {
1061 return ret;
1062 }
1063
1064 latest_epoch = info.epoch;
1065
1066 return 0;
1067}
1068
b3b6e05e 1069int RGWPeriod::use_latest_epoch(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1070{
1071 RGWPeriodLatestEpochInfo info;
b3b6e05e 1072 int ret = read_latest_epoch(dpp, info, y);
11fdf7f2
TL
1073 if (ret < 0) {
1074 return ret;
1075 }
1076
1077 epoch = info.epoch;
1078
1079 return 0;
1080}
1081
b3b6e05e
TL
1082int RGWPeriod::set_latest_epoch(const DoutPrefixProvider *dpp,
1083 optional_yield y,
f67539c2 1084 epoch_t epoch, bool exclusive,
11fdf7f2
TL
1085 RGWObjVersionTracker *objv)
1086{
1087 string oid = get_period_oid_prefix() + get_latest_epoch_oid();
1088
1089 rgw_pool pool(get_pool(cct));
1090 bufferlist bl;
1091
1092 RGWPeriodLatestEpochInfo info;
1093 info.epoch = epoch;
1094
1095 using ceph::encode;
1096 encode(info, bl);
1097
1098 auto obj_ctx = sysobj_svc->init_obj_ctx();
1099 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
1100 return sysobj.wop()
1101 .set_exclusive(exclusive)
b3b6e05e 1102 .write(dpp, bl, y);
11fdf7f2
TL
1103}
1104
b3b6e05e 1105int RGWPeriod::update_latest_epoch(const DoutPrefixProvider *dpp, epoch_t epoch, optional_yield y)
11fdf7f2
TL
1106{
1107 static constexpr int MAX_RETRIES = 20;
1108
1109 for (int i = 0; i < MAX_RETRIES; i++) {
1110 RGWPeriodLatestEpochInfo info;
1111 RGWObjVersionTracker objv;
1112 bool exclusive = false;
1113
1114 // read existing epoch
b3b6e05e 1115 int r = read_latest_epoch(dpp, info, y, &objv);
11fdf7f2
TL
1116 if (r == -ENOENT) {
1117 // use an exclusive create to set the epoch atomically
1118 exclusive = true;
b3b6e05e 1119 ldpp_dout(dpp, 20) << "creating initial latest_epoch=" << epoch
11fdf7f2
TL
1120 << " for period=" << id << dendl;
1121 } else if (r < 0) {
b3b6e05e 1122 ldpp_dout(dpp, 0) << "ERROR: failed to read latest_epoch" << dendl;
11fdf7f2
TL
1123 return r;
1124 } else if (epoch <= info.epoch) {
1125 r = -EEXIST; // fail with EEXIST if epoch is not newer
b3b6e05e 1126 ldpp_dout(dpp, 10) << "found existing latest_epoch " << info.epoch
11fdf7f2
TL
1127 << " >= given epoch " << epoch << ", returning r=" << r << dendl;
1128 return r;
1129 } else {
b3b6e05e 1130 ldpp_dout(dpp, 20) << "updating latest_epoch from " << info.epoch
11fdf7f2
TL
1131 << " -> " << epoch << " on period=" << id << dendl;
1132 }
1133
b3b6e05e 1134 r = set_latest_epoch(dpp, y, epoch, exclusive, &objv);
11fdf7f2
TL
1135 if (r == -EEXIST) {
1136 continue; // exclusive create raced with another update, retry
1137 } else if (r == -ECANCELED) {
1138 continue; // write raced with a conflicting version, retry
1139 }
1140 if (r < 0) {
b3b6e05e 1141 ldpp_dout(dpp, 0) << "ERROR: failed to write latest_epoch" << dendl;
11fdf7f2
TL
1142 return r;
1143 }
1144 return 0; // return success
1145 }
1146
1147 return -ECANCELED; // fail after max retries
1148}
1149
b3b6e05e 1150int RGWPeriod::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1151{
1152 rgw_pool pool(get_pool(cct));
1153
1154 // delete the object for each period epoch
1155 for (epoch_t e = 1; e <= epoch; e++) {
1156 RGWPeriod p{get_id(), e};
1157 rgw_raw_obj oid{pool, p.get_period_oid()};
1158 auto obj_ctx = sysobj_svc->init_obj_ctx();
1159 auto sysobj = sysobj_svc->get_obj(obj_ctx, oid);
b3b6e05e 1160 int ret = sysobj.wop().remove(dpp, y);
11fdf7f2 1161 if (ret < 0) {
b3b6e05e 1162 ldpp_dout(dpp, 0) << "WARNING: failed to delete period object " << oid
11fdf7f2
TL
1163 << ": " << cpp_strerror(-ret) << dendl;
1164 }
1165 }
1166
1167 // delete the .latest_epoch object
1168 rgw_raw_obj oid{pool, get_period_oid_prefix() + get_latest_epoch_oid()};
1169 auto obj_ctx = sysobj_svc->init_obj_ctx();
1170 auto sysobj = sysobj_svc->get_obj(obj_ctx, oid);
b3b6e05e 1171 int ret = sysobj.wop().remove(dpp, y);
11fdf7f2 1172 if (ret < 0) {
b3b6e05e 1173 ldpp_dout(dpp, 0) << "WARNING: failed to delete period object " << oid
11fdf7f2
TL
1174 << ": " << cpp_strerror(-ret) << dendl;
1175 }
1176 return ret;
1177}
1178
b3b6e05e 1179int RGWPeriod::read_info(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1180{
1181 rgw_pool pool(get_pool(cct));
1182
1183 bufferlist bl;
1184
1185 auto obj_ctx = sysobj_svc->init_obj_ctx();
1186 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj{pool, get_period_oid()});
b3b6e05e 1187 int ret = sysobj.rop().read(dpp, &bl, y);
11fdf7f2 1188 if (ret < 0) {
b3b6e05e 1189 ldpp_dout(dpp, 0) << "failed reading obj info from " << pool << ":" << get_period_oid() << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1190 return ret;
1191 }
1192
1193 try {
1194 using ceph::decode;
1195 auto iter = bl.cbegin();
1196 decode(*this, iter);
1197 } catch (buffer::error& err) {
b3b6e05e 1198 ldpp_dout(dpp, 0) << "ERROR: failed to decode obj from " << pool << ":" << get_period_oid() << dendl;
11fdf7f2
TL
1199 return -EIO;
1200 }
1201
1202 return 0;
1203}
1204
b3b6e05e 1205int RGWPeriod::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
1206{
1207 int ret;
1208
1209 /* create unique id */
1210 uuid_d new_uuid;
1211 char uuid_str[37];
1212 new_uuid.generate_random();
1213 new_uuid.print(uuid_str);
1214 id = uuid_str;
1215
1216 epoch = FIRST_EPOCH;
1217
1218 period_map.id = id;
f67539c2 1219
b3b6e05e 1220 ret = store_info(dpp, exclusive, y);
11fdf7f2 1221 if (ret < 0) {
b3b6e05e 1222 ldpp_dout(dpp, 0) << "ERROR: storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1223 return ret;
1224 }
1225
b3b6e05e 1226 ret = set_latest_epoch(dpp, y, epoch);
11fdf7f2 1227 if (ret < 0) {
b3b6e05e 1228 ldpp_dout(dpp, 0) << "ERROR: setting latest epoch " << id << ": " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1229 }
1230
1231 return ret;
1232}
1233
b3b6e05e 1234int RGWPeriod::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
11fdf7f2
TL
1235{
1236 rgw_pool pool(get_pool(cct));
1237
1238 string oid = get_period_oid();
1239 bufferlist bl;
1240 using ceph::encode;
1241 encode(*this, bl);
1242
1243 auto obj_ctx = sysobj_svc->init_obj_ctx();
1244 auto sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
1245 return sysobj.wop()
1246 .set_exclusive(exclusive)
b3b6e05e 1247 .write(dpp, bl, y);
11fdf7f2
TL
1248}
1249
1250rgw_pool RGWPeriod::get_pool(CephContext *cct) const
1251{
1252 if (cct->_conf->rgw_period_root_pool.empty()) {
1253 return rgw_pool(RGW_DEFAULT_PERIOD_ROOT_POOL);
1254 }
1255 return rgw_pool(cct->_conf->rgw_period_root_pool);
1256}
1257
b3b6e05e 1258int RGWPeriod::add_zonegroup(const DoutPrefixProvider *dpp, const RGWZoneGroup& zonegroup, optional_yield y)
11fdf7f2
TL
1259{
1260 if (zonegroup.realm_id != realm_id) {
1261 return 0;
1262 }
1263 int ret = period_map.update(zonegroup, cct);
1264 if (ret < 0) {
b3b6e05e 1265 ldpp_dout(dpp, 0) << "ERROR: updating period map: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1266 return ret;
1267 }
1268
b3b6e05e 1269 return store_info(dpp, false, y);
11fdf7f2
TL
1270}
1271
b3b6e05e 1272int RGWPeriod::update(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1273{
1274 auto zone_svc = sysobj_svc->get_zone_svc();
b3b6e05e 1275 ldpp_dout(dpp, 20) << __func__ << " realm " << realm_id << " period " << get_id() << dendl;
11fdf7f2 1276 list<string> zonegroups;
b3b6e05e 1277 int ret = zone_svc->list_zonegroups(dpp, zonegroups);
11fdf7f2 1278 if (ret < 0) {
b3b6e05e 1279 ldpp_dout(dpp, 0) << "ERROR: failed to list zonegroups: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1280 return ret;
1281 }
1282
1283 // clear zone short ids of removed zones. period_map.update() will add the
1284 // remaining zones back
1285 period_map.short_zone_ids.clear();
1286
1287 for (auto& iter : zonegroups) {
1288 RGWZoneGroup zg(string(), iter);
b3b6e05e 1289 ret = zg.init(dpp, cct, sysobj_svc, y);
11fdf7f2 1290 if (ret < 0) {
b3b6e05e 1291 ldpp_dout(dpp, 0) << "WARNING: zg.init() failed: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1292 continue;
1293 }
1294
1295 if (zg.realm_id != realm_id) {
b3b6e05e 1296 ldpp_dout(dpp, 20) << "skipping zonegroup " << zg.get_name() << " zone realm id " << zg.realm_id << ", not on our realm " << realm_id << dendl;
11fdf7f2
TL
1297 continue;
1298 }
1299
1300 if (zg.master_zone.empty()) {
b3b6e05e 1301 ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name() << " should have a master zone " << dendl;
11fdf7f2
TL
1302 return -EINVAL;
1303 }
1304
1305 if (zg.zones.find(zg.master_zone) == zg.zones.end()) {
b3b6e05e 1306 ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name()
11fdf7f2
TL
1307 << " has a non existent master zone "<< dendl;
1308 return -EINVAL;
1309 }
1310
1311 if (zg.is_master_zonegroup()) {
1312 master_zonegroup = zg.get_id();
1313 master_zone = zg.master_zone;
1314 }
1315
1316 int ret = period_map.update(zg, cct);
1317 if (ret < 0) {
1318 return ret;
1319 }
1320 }
1321
b3b6e05e 1322 ret = period_config.read(dpp, sysobj_svc, realm_id, y);
11fdf7f2 1323 if (ret < 0 && ret != -ENOENT) {
b3b6e05e 1324 ldpp_dout(dpp, 0) << "ERROR: failed to read period config: "
11fdf7f2
TL
1325 << cpp_strerror(ret) << dendl;
1326 return ret;
1327 }
1328 return 0;
1329}
1330
b3b6e05e 1331int RGWPeriod::reflect(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1332{
1333 for (auto& iter : period_map.zonegroups) {
1334 RGWZoneGroup& zg = iter.second;
1335 zg.reinit_instance(cct, sysobj_svc);
b3b6e05e 1336 int r = zg.write(dpp, false, y);
11fdf7f2 1337 if (r < 0) {
b3b6e05e 1338 ldpp_dout(dpp, 0) << "ERROR: failed to store zonegroup info for zonegroup=" << iter.first << ": " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1339 return r;
1340 }
1341 if (zg.is_master_zonegroup()) {
1342 // set master as default if no default exists
b3b6e05e 1343 r = zg.set_as_default(dpp, y, true);
11fdf7f2 1344 if (r == 0) {
b3b6e05e 1345 ldpp_dout(dpp, 1) << "Set the period's master zonegroup " << zg.get_id()
11fdf7f2
TL
1346 << " as the default" << dendl;
1347 }
1348 }
1349 }
1350
b3b6e05e 1351 int r = period_config.write(dpp, sysobj_svc, realm_id, y);
11fdf7f2 1352 if (r < 0) {
b3b6e05e 1353 ldpp_dout(dpp, 0) << "ERROR: failed to store period config: "
11fdf7f2
TL
1354 << cpp_strerror(-r) << dendl;
1355 return r;
1356 }
1357 return 0;
1358}
1359
1360void RGWPeriod::fork()
1361{
1362 ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << id << dendl;
1363 predecessor_uuid = id;
1364 id = get_staging_id(realm_id);
1365 period_map.reset();
1366 realm_epoch++;
1367}
1368
b3b6e05e 1369static int read_sync_status(const DoutPrefixProvider *dpp, rgw::sal::RGWRadosStore *store, rgw_meta_sync_status *sync_status)
11fdf7f2
TL
1370{
1371 // initialize a sync status manager to read the status
9f95a23c 1372 RGWMetaSyncStatusManager mgr(store, store->svc()->rados->get_async_processor());
b3b6e05e 1373 int r = mgr.init(dpp);
11fdf7f2
TL
1374 if (r < 0) {
1375 return r;
1376 }
b3b6e05e 1377 r = mgr.read_sync_status(dpp, sync_status);
11fdf7f2
TL
1378 mgr.stop();
1379 return r;
1380}
1381
b3b6e05e
TL
1382int RGWPeriod::update_sync_status(const DoutPrefixProvider *dpp,
1383 rgw::sal::RGWRadosStore *store, /* for now */
11fdf7f2
TL
1384 const RGWPeriod &current_period,
1385 std::ostream& error_stream,
1386 bool force_if_stale)
1387{
1388 rgw_meta_sync_status status;
b3b6e05e 1389 int r = read_sync_status(dpp, store, &status);
11fdf7f2 1390 if (r < 0) {
b3b6e05e 1391 ldpp_dout(dpp, 0) << "period failed to read sync status: "
11fdf7f2
TL
1392 << cpp_strerror(-r) << dendl;
1393 return r;
1394 }
1395
1396 std::vector<std::string> markers;
1397
1398 const auto current_epoch = current_period.get_realm_epoch();
1399 if (current_epoch != status.sync_info.realm_epoch) {
1400 // no sync status markers for the current period
1401 ceph_assert(current_epoch > status.sync_info.realm_epoch);
1402 const int behind = current_epoch - status.sync_info.realm_epoch;
1403 if (!force_if_stale && current_epoch > 1) {
1404 error_stream << "ERROR: This zone is " << behind << " period(s) behind "
1405 "the current master zone in metadata sync. If this zone is promoted "
1406 "to master, any metadata changes during that time are likely to "
1407 "be lost.\n"
1408 "Waiting for this zone to catch up on metadata sync (see "
1409 "'radosgw-admin sync status') is recommended.\n"
1410 "To promote this zone to master anyway, add the flag "
1411 "--yes-i-really-mean-it." << std::endl;
1412 return -EINVAL;
1413 }
1414 // empty sync status markers - other zones will skip this period during
1415 // incremental metadata sync
1416 markers.resize(status.sync_info.num_shards);
1417 } else {
1418 markers.reserve(status.sync_info.num_shards);
1419 for (auto& i : status.sync_markers) {
1420 auto& marker = i.second;
1421 // filter out markers from other periods
1422 if (marker.realm_epoch != current_epoch) {
1423 marker.marker.clear();
1424 }
1425 markers.emplace_back(std::move(marker.marker));
1426 }
1427 }
1428
1429 std::swap(sync_status, markers);
1430 return 0;
1431}
1432
b3b6e05e
TL
1433int RGWPeriod::commit(const DoutPrefixProvider *dpp,
1434 rgw::sal::RGWRadosStore *store,
11fdf7f2 1435 RGWRealm& realm, const RGWPeriod& current_period,
f67539c2
TL
1436 std::ostream& error_stream, optional_yield y,
1437 bool force_if_stale)
11fdf7f2
TL
1438{
1439 auto zone_svc = sysobj_svc->get_zone_svc();
b3b6e05e 1440 ldpp_dout(dpp, 20) << __func__ << " realm " << realm.get_id() << " period " << current_period.get_id() << dendl;
11fdf7f2
TL
1441 // gateway must be in the master zone to commit
1442 if (master_zone != zone_svc->get_zone_params().get_id()) {
1443 error_stream << "Cannot commit period on zone "
1444 << zone_svc->get_zone_params().get_id() << ", it must be sent to "
1445 "the period's master zone " << master_zone << '.' << std::endl;
1446 return -EINVAL;
1447 }
1448 // period predecessor must match current period
1449 if (predecessor_uuid != current_period.get_id()) {
1450 error_stream << "Period predecessor " << predecessor_uuid
1451 << " does not match current period " << current_period.get_id()
1452 << ". Use 'period pull' to get the latest period from the master, "
1453 "reapply your changes, and try again." << std::endl;
1454 return -EINVAL;
1455 }
1456 // realm epoch must be 1 greater than current period
1457 if (realm_epoch != current_period.get_realm_epoch() + 1) {
1458 error_stream << "Period's realm epoch " << realm_epoch
1459 << " does not come directly after current realm epoch "
1460 << current_period.get_realm_epoch() << ". Use 'realm pull' to get the "
1461 "latest realm and period from the master zone, reapply your changes, "
1462 "and try again." << std::endl;
1463 return -EINVAL;
1464 }
1465 // did the master zone change?
1466 if (master_zone != current_period.get_master_zone()) {
1467 // store the current metadata sync status in the period
b3b6e05e 1468 int r = update_sync_status(dpp, store, current_period, error_stream, force_if_stale);
11fdf7f2 1469 if (r < 0) {
b3b6e05e 1470 ldpp_dout(dpp, 0) << "failed to update metadata sync status: "
11fdf7f2
TL
1471 << cpp_strerror(-r) << dendl;
1472 return r;
1473 }
1474 // create an object with a new period id
b3b6e05e 1475 r = create(dpp, y, true);
11fdf7f2 1476 if (r < 0) {
b3b6e05e 1477 ldpp_dout(dpp, 0) << "failed to create new period: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1478 return r;
1479 }
1480 // set as current period
b3b6e05e 1481 r = realm.set_current_period(dpp, *this, y);
11fdf7f2 1482 if (r < 0) {
b3b6e05e 1483 ldpp_dout(dpp, 0) << "failed to update realm's current period: "
11fdf7f2
TL
1484 << cpp_strerror(-r) << dendl;
1485 return r;
1486 }
b3b6e05e 1487 ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period "
11fdf7f2 1488 << id << dendl;
b3b6e05e 1489 realm.notify_new_period(dpp, *this, y);
11fdf7f2
TL
1490 return 0;
1491 }
1492 // period must be based on current epoch
1493 if (epoch != current_period.get_epoch()) {
1494 error_stream << "Period epoch " << epoch << " does not match "
1495 "predecessor epoch " << current_period.get_epoch()
1496 << ". Use 'period pull' to get the latest epoch from the master zone, "
1497 "reapply your changes, and try again." << std::endl;
1498 return -EINVAL;
1499 }
1500 // set period as next epoch
1501 set_id(current_period.get_id());
1502 set_epoch(current_period.get_epoch() + 1);
1503 set_predecessor(current_period.get_predecessor());
1504 realm_epoch = current_period.get_realm_epoch();
1505 // write the period to rados
b3b6e05e 1506 int r = store_info(dpp, false, y);
11fdf7f2 1507 if (r < 0) {
b3b6e05e 1508 ldpp_dout(dpp, 0) << "failed to store period: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1509 return r;
1510 }
1511 // set as latest epoch
b3b6e05e 1512 r = update_latest_epoch(dpp, epoch, y);
11fdf7f2
TL
1513 if (r == -EEXIST) {
1514 // already have this epoch (or a more recent one)
1515 return 0;
1516 }
1517 if (r < 0) {
b3b6e05e 1518 ldpp_dout(dpp, 0) << "failed to set latest epoch: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1519 return r;
1520 }
b3b6e05e 1521 r = reflect(dpp, y);
11fdf7f2 1522 if (r < 0) {
b3b6e05e 1523 ldpp_dout(dpp, 0) << "failed to update local objects: " << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1524 return r;
1525 }
b3b6e05e 1526 ldpp_dout(dpp, 4) << "Committed new epoch " << epoch
11fdf7f2 1527 << " for period " << id << dendl;
b3b6e05e 1528 realm.notify_new_period(dpp, *this, y);
11fdf7f2
TL
1529 return 0;
1530}
1531
b3b6e05e 1532int RGWZoneParams::create_default(const DoutPrefixProvider *dpp, optional_yield y, bool old_format)
11fdf7f2
TL
1533{
1534 name = default_zone_name;
1535
b3b6e05e 1536 int r = create(dpp, y);
11fdf7f2
TL
1537 if (r < 0) {
1538 return r;
1539 }
1540
1541 if (old_format) {
1542 name = id;
1543 }
1544
1545 return r;
1546}
1547
1548
f67539c2 1549namespace {
b3b6e05e
TL
1550int get_zones_pool_set(const DoutPrefixProvider *dpp,
1551 CephContext* cct,
11fdf7f2
TL
1552 RGWSI_SysObj* sysobj_svc,
1553 const list<string>& zones,
1554 const string& my_zone_id,
f67539c2
TL
1555 set<rgw_pool>& pool_names,
1556 optional_yield y)
11fdf7f2
TL
1557{
1558 for(auto const& iter : zones) {
1559 RGWZoneParams zone(iter);
b3b6e05e 1560 int r = zone.init(dpp, cct, sysobj_svc, y);
11fdf7f2 1561 if (r < 0) {
b3b6e05e 1562 ldpp_dout(dpp, 0) << "Error: init zone " << iter << ":" << cpp_strerror(-r) << dendl;
11fdf7f2
TL
1563 return r;
1564 }
1565 if (zone.get_id() != my_zone_id) {
1566 pool_names.insert(zone.domain_root);
11fdf7f2
TL
1567 pool_names.insert(zone.control_pool);
1568 pool_names.insert(zone.gc_pool);
1569 pool_names.insert(zone.log_pool);
1570 pool_names.insert(zone.intent_log_pool);
1571 pool_names.insert(zone.usage_log_pool);
1572 pool_names.insert(zone.user_keys_pool);
1573 pool_names.insert(zone.user_email_pool);
1574 pool_names.insert(zone.user_swift_pool);
1575 pool_names.insert(zone.user_uid_pool);
1576 pool_names.insert(zone.otp_pool);
1577 pool_names.insert(zone.roles_pool);
1578 pool_names.insert(zone.reshard_pool);
f67539c2 1579 pool_names.insert(zone.notif_pool);
11fdf7f2
TL
1580 for(auto& iter : zone.placement_pools) {
1581 pool_names.insert(iter.second.index_pool);
1582 for (auto& pi : iter.second.storage_classes.get_all()) {
1583 if (pi.second.data_pool) {
1584 pool_names.insert(pi.second.data_pool.get());
1585 }
1586 }
1587 pool_names.insert(iter.second.data_extra_pool);
1588 }
f91f0fd5 1589 pool_names.insert(zone.oidc_pool);
11fdf7f2
TL
1590 }
1591 }
1592 return 0;
1593}
1594
1595rgw_pool fix_zone_pool_dup(set<rgw_pool> pools,
1596 const string& default_prefix,
1597 const string& default_suffix,
1598 const rgw_pool& suggested_pool)
1599{
1600 string suggested_name = suggested_pool.to_str();
1601
1602 string prefix = default_prefix;
1603 string suffix = default_suffix;
1604
1605 if (!suggested_pool.empty()) {
1606 prefix = suggested_name.substr(0, suggested_name.find("."));
1607 suffix = suggested_name.substr(prefix.length());
1608 }
1609
1610 rgw_pool pool(prefix + suffix);
1611
1612 if (pools.find(pool) == pools.end()) {
1613 return pool;
1614 } else {
1615 while(true) {
1616 pool = prefix + "_" + std::to_string(std::rand()) + suffix;
1617 if (pools.find(pool) == pools.end()) {
1618 return pool;
1619 }
1620 }
1621 }
1622}
f67539c2 1623}
11fdf7f2 1624
b3b6e05e 1625int RGWZoneParams::fix_pool_names(const DoutPrefixProvider *dpp, optional_yield y)
11fdf7f2
TL
1626{
1627
1628 list<string> zones;
b3b6e05e 1629 int r = zone_svc->list_zones(dpp, zones);
11fdf7f2 1630 if (r < 0) {
b3b6e05e 1631 ldpp_dout(dpp, 10) << "WARNING: store->list_zones() returned r=" << r << dendl;
11fdf7f2
TL
1632 }
1633
1634 set<rgw_pool> pools;
b3b6e05e 1635 r = get_zones_pool_set(dpp, cct, sysobj_svc, zones, id, pools, y);
11fdf7f2 1636 if (r < 0) {
b3b6e05e 1637 ldpp_dout(dpp, 0) << "Error: get_zones_pool_names" << r << dendl;
11fdf7f2
TL
1638 return r;
1639 }
1640
1641 domain_root = fix_zone_pool_dup(pools, name, ".rgw.meta:root", domain_root);
11fdf7f2
TL
1642 control_pool = fix_zone_pool_dup(pools, name, ".rgw.control", control_pool);
1643 gc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:gc", gc_pool);
1644 lc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:lc", lc_pool);
1645 log_pool = fix_zone_pool_dup(pools, name, ".rgw.log", log_pool);
1646 intent_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:intent", intent_log_pool);
1647 usage_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:usage", usage_log_pool);
1648 user_keys_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.keys", user_keys_pool);
1649 user_email_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.email", user_email_pool);
1650 user_swift_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.swift", user_swift_pool);
1651 user_uid_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.uid", user_uid_pool);
1652 roles_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:roles", roles_pool);
1653 reshard_pool = fix_zone_pool_dup(pools, name, ".rgw.log:reshard", reshard_pool);
1654 otp_pool = fix_zone_pool_dup(pools, name, ".rgw.otp", otp_pool);
f91f0fd5 1655 oidc_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:oidc", oidc_pool);
f67539c2 1656 notif_pool = fix_zone_pool_dup(pools, name ,".rgw.log:notif", notif_pool);
11fdf7f2
TL
1657
1658 for(auto& iter : placement_pools) {
1659 iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix,
1660 iter.second.index_pool);
1661 for (auto& pi : iter.second.storage_classes.get_all()) {
1662 if (pi.second.data_pool) {
1663 rgw_pool& pool = pi.second.data_pool.get();
1664 pool = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
1665 pool);
1666 }
1667 }
1668 iter.second.data_extra_pool= fix_zone_pool_dup(pools, name, "." + default_storage_extra_pool_suffix,
1669 iter.second.data_extra_pool);
1670 }
1671
1672 return 0;
1673}
1674
b3b6e05e 1675int RGWZoneParams::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
1676{
1677 /* check for old pools config */
1678 rgw_raw_obj obj(domain_root, avail_pools);
1679 auto obj_ctx = sysobj_svc->init_obj_ctx();
1680 auto sysobj = sysobj_svc->get_obj(obj_ctx, obj);
b3b6e05e 1681 int r = sysobj.rop().stat(y, dpp);
11fdf7f2 1682 if (r < 0) {
b3b6e05e 1683 ldpp_dout(dpp, 10) << "couldn't find old data placement pools config, setting up new ones for the zone" << dendl;
11fdf7f2
TL
1684 /* a new system, let's set new placement info */
1685 RGWZonePlacementInfo default_placement;
1686 default_placement.index_pool = name + "." + default_bucket_index_pool_suffix;
1687 rgw_pool pool = name + "." + default_storage_pool_suffix;
1688 default_placement.storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &pool, nullptr);
1689 default_placement.data_extra_pool = name + "." + default_storage_extra_pool_suffix;
1690 placement_pools["default-placement"] = default_placement;
1691 }
1692
b3b6e05e 1693 r = fix_pool_names(dpp, y);
11fdf7f2 1694 if (r < 0) {
b3b6e05e 1695 ldpp_dout(dpp, 0) << "ERROR: fix_pool_names returned r=" << r << dendl;
11fdf7f2
TL
1696 return r;
1697 }
1698
b3b6e05e 1699 r = RGWSystemMetaObj::create(dpp, y, exclusive);
11fdf7f2
TL
1700 if (r < 0) {
1701 return r;
1702 }
1703
1704 // try to set as default. may race with another create, so pass exclusive=true
1705 // so we don't override an existing default
b3b6e05e 1706 r = set_as_default(dpp, y, true);
11fdf7f2 1707 if (r < 0 && r != -EEXIST) {
b3b6e05e 1708 ldpp_dout(dpp, 10) << "WARNING: failed to set zone as default, r=" << r << dendl;
11fdf7f2
TL
1709 }
1710
1711 return 0;
1712}
1713
1714rgw_pool RGWZoneParams::get_pool(CephContext *cct) const
1715{
1716 if (cct->_conf->rgw_zone_root_pool.empty()) {
1717 return rgw_pool(RGW_DEFAULT_ZONE_ROOT_POOL);
1718 }
1719
1720 return rgw_pool(cct->_conf->rgw_zone_root_pool);
1721}
1722
1723const string RGWZoneParams::get_default_oid(bool old_format) const
1724{
1725 if (old_format) {
1726 return cct->_conf->rgw_default_zone_info_oid;
1727 }
1728
1729 return cct->_conf->rgw_default_zone_info_oid + "." + realm_id;
1730}
1731
1732const string& RGWZoneParams::get_names_oid_prefix() const
1733{
1734 return zone_names_oid_prefix;
1735}
1736
1737const string& RGWZoneParams::get_info_oid_prefix(bool old_format) const
1738{
1739 return zone_info_oid_prefix;
1740}
1741
1742const string& RGWZoneParams::get_predefined_name(CephContext *cct) const {
1743 return cct->_conf->rgw_zone;
1744}
1745
b3b6e05e
TL
1746int RGWZoneParams::init(const DoutPrefixProvider *dpp,
1747 CephContext *cct, RGWSI_SysObj *sysobj_svc,
f67539c2 1748 optional_yield y, bool setup_obj, bool old_format)
11fdf7f2
TL
1749{
1750 if (name.empty()) {
1751 name = cct->_conf->rgw_zone;
1752 }
1753
b3b6e05e 1754 return RGWSystemMetaObj::init(dpp, cct, sysobj_svc, y, setup_obj, old_format);
11fdf7f2
TL
1755}
1756
b3b6e05e 1757int RGWZoneParams::read_default_id(const DoutPrefixProvider *dpp, string& default_id, optional_yield y,
f67539c2 1758 bool old_format)
11fdf7f2
TL
1759{
1760 if (realm_id.empty()) {
1761 /* try using default realm */
1762 RGWRealm realm;
b3b6e05e 1763 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
1764 //no default realm exist
1765 if (ret < 0) {
b3b6e05e 1766 return read_id(dpp, default_zone_name, default_id, y);
11fdf7f2
TL
1767 }
1768 realm_id = realm.get_id();
1769 }
1770
b3b6e05e 1771 return RGWSystemMetaObj::read_default_id(dpp, default_id, y, old_format);
11fdf7f2
TL
1772}
1773
1774
b3b6e05e 1775int RGWZoneParams::set_as_default(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive)
11fdf7f2
TL
1776{
1777 if (realm_id.empty()) {
1778 /* try using default realm */
1779 RGWRealm realm;
b3b6e05e 1780 int ret = realm.init(dpp, cct, sysobj_svc, y);
11fdf7f2 1781 if (ret < 0) {
b3b6e05e 1782 ldpp_dout(dpp, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
1783 return -EINVAL;
1784 }
1785 realm_id = realm.get_id();
1786 }
1787
b3b6e05e 1788 return RGWSystemMetaObj::set_as_default(dpp, y, exclusive);
11fdf7f2
TL
1789}
1790
1791const string& RGWZoneParams::get_compression_type(const rgw_placement_rule& placement_rule) const
1792{
1793 static const std::string NONE{"none"};
1794 auto p = placement_pools.find(placement_rule.name);
1795 if (p == placement_pools.end()) {
1796 return NONE;
1797 }
eafe8130 1798 const auto& type = p->second.get_compression_type(placement_rule.get_storage_class());
11fdf7f2
TL
1799 return !type.empty() ? type : NONE;
1800}
1801
1802void RGWPeriodMap::encode(bufferlist& bl) const {
1803 ENCODE_START(2, 1, bl);
1804 encode(id, bl);
1805 encode(zonegroups, bl);
1806 encode(master_zonegroup, bl);
1807 encode(short_zone_ids, bl);
1808 ENCODE_FINISH(bl);
1809}
1810
1811void RGWPeriodMap::decode(bufferlist::const_iterator& bl) {
1812 DECODE_START(2, bl);
1813 decode(id, bl);
1814 decode(zonegroups, bl);
1815 decode(master_zonegroup, bl);
1816 if (struct_v >= 2) {
1817 decode(short_zone_ids, bl);
1818 }
1819 DECODE_FINISH(bl);
1820
1821 zonegroups_by_api.clear();
1822 for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
1823 iter != zonegroups.end(); ++iter) {
1824 RGWZoneGroup& zonegroup = iter->second;
1825 zonegroups_by_api[zonegroup.api_name] = zonegroup;
1826 if (zonegroup.is_master_zonegroup()) {
1827 master_zonegroup = zonegroup.get_id();
1828 }
1829 }
1830}
1831
1832// run an MD5 hash on the zone_id and return the first 32 bits
1833static uint32_t gen_short_zone_id(const std::string zone_id)
1834{
1835 unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
1836 MD5 hash;
1837 hash.Update((const unsigned char *)zone_id.c_str(), zone_id.size());
1838 hash.Final(md5);
1839
1840 uint32_t short_id;
1841 memcpy((char *)&short_id, md5, sizeof(short_id));
1842 return std::max(short_id, 1u);
1843}
1844
1845int RGWPeriodMap::update(const RGWZoneGroup& zonegroup, CephContext *cct)
1846{
1847 if (zonegroup.is_master_zonegroup() && (!master_zonegroup.empty() && zonegroup.get_id() != master_zonegroup)) {
1848 ldout(cct,0) << "Error updating periodmap, multiple master zonegroups configured "<< dendl;
1849 ldout(cct,0) << "master zonegroup: " << master_zonegroup << " and " << zonegroup.get_id() <<dendl;
1850 return -EINVAL;
1851 }
1852 map<string, RGWZoneGroup>::iterator iter = zonegroups.find(zonegroup.get_id());
1853 if (iter != zonegroups.end()) {
1854 RGWZoneGroup& old_zonegroup = iter->second;
1855 if (!old_zonegroup.api_name.empty()) {
1856 zonegroups_by_api.erase(old_zonegroup.api_name);
1857 }
1858 }
1859 zonegroups[zonegroup.get_id()] = zonegroup;
1860
1861 if (!zonegroup.api_name.empty()) {
1862 zonegroups_by_api[zonegroup.api_name] = zonegroup;
1863 }
1864
1865 if (zonegroup.is_master_zonegroup()) {
1866 master_zonegroup = zonegroup.get_id();
1867 } else if (master_zonegroup == zonegroup.get_id()) {
1868 master_zonegroup = "";
1869 }
1870
1871 for (auto& i : zonegroup.zones) {
1872 auto& zone = i.second;
1873 if (short_zone_ids.find(zone.id) != short_zone_ids.end()) {
1874 continue;
1875 }
1876 // calculate the zone's short id
1877 uint32_t short_id = gen_short_zone_id(zone.id);
1878
1879 // search for an existing zone with the same short id
1880 for (auto& s : short_zone_ids) {
1881 if (s.second == short_id) {
1882 ldout(cct, 0) << "New zone '" << zone.name << "' (" << zone.id
1883 << ") generates the same short_zone_id " << short_id
1884 << " as existing zone id " << s.first << dendl;
1885 return -EEXIST;
1886 }
1887 }
1888
1889 short_zone_ids[zone.id] = short_id;
1890 }
1891
1892 return 0;
1893}
1894
1895uint32_t RGWPeriodMap::get_zone_short_id(const string& zone_id) const
1896{
1897 auto i = short_zone_ids.find(zone_id);
1898 if (i == short_zone_ids.end()) {
1899 return 0;
1900 }
1901 return i->second;
1902}
1903
b3b6e05e 1904int RGWZoneGroupMap::read(const DoutPrefixProvider *dpp, CephContext *cct, RGWSI_SysObj *sysobj_svc, optional_yield y)
11fdf7f2
TL
1905{
1906
1907 RGWPeriod period;
b3b6e05e 1908 int ret = period.init(dpp, cct, sysobj_svc, y);
11fdf7f2
TL
1909 if (ret < 0) {
1910 cerr << "failed to read current period info: " << cpp_strerror(ret);
1911 return ret;
1912 }
f67539c2 1913
11fdf7f2
TL
1914 bucket_quota = period.get_config().bucket_quota;
1915 user_quota = period.get_config().user_quota;
1916 zonegroups = period.get_map().zonegroups;
1917 zonegroups_by_api = period.get_map().zonegroups_by_api;
1918 master_zonegroup = period.get_map().master_zonegroup;
1919
1920 return 0;
1921}
1922
1923void RGWRegionMap::encode(bufferlist& bl) const {
1924 ENCODE_START( 3, 1, bl);
1925 encode(regions, bl);
1926 encode(master_region, bl);
1927 encode(bucket_quota, bl);
1928 encode(user_quota, bl);
1929 ENCODE_FINISH(bl);
1930}
1931
1932void RGWRegionMap::decode(bufferlist::const_iterator& bl) {
1933 DECODE_START(3, bl);
1934 decode(regions, bl);
1935 decode(master_region, bl);
1936 if (struct_v >= 2)
1937 decode(bucket_quota, bl);
1938 if (struct_v >= 3)
1939 decode(user_quota, bl);
1940 DECODE_FINISH(bl);
1941}
1942
1943void RGWZoneGroupMap::encode(bufferlist& bl) const {
1944 ENCODE_START( 3, 1, bl);
1945 encode(zonegroups, bl);
1946 encode(master_zonegroup, bl);
1947 encode(bucket_quota, bl);
1948 encode(user_quota, bl);
1949 ENCODE_FINISH(bl);
1950}
1951
1952void RGWZoneGroupMap::decode(bufferlist::const_iterator& bl) {
1953 DECODE_START(3, bl);
1954 decode(zonegroups, bl);
1955 decode(master_zonegroup, bl);
1956 if (struct_v >= 2)
1957 decode(bucket_quota, bl);
1958 if (struct_v >= 3)
1959 decode(user_quota, bl);
1960 DECODE_FINISH(bl);
1961
1962 zonegroups_by_api.clear();
1963 for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
1964 iter != zonegroups.end(); ++iter) {
1965 RGWZoneGroup& zonegroup = iter->second;
1966 zonegroups_by_api[zonegroup.api_name] = zonegroup;
1967 if (zonegroup.is_master_zonegroup()) {
1968 master_zonegroup = zonegroup.get_name();
1969 }
1970 }
1971}
1972
1973