1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include "common/errno.h"
7 #include "rgw_realm_watcher.h"
8 #include "rgw_meta_sync_status.h"
11 #include "services/svc_zone.h"
12 #include "services/svc_sys_obj.h"
14 #define dout_subsys ceph_subsys_rgw
16 namespace rgw_zone_defaults
{
18 std::string zone_info_oid_prefix
= "zone_info.";
19 std::string zone_names_oid_prefix
= "zone_names.";
20 std::string region_info_oid_prefix
= "region_info.";
21 std::string realm_names_oid_prefix
= "realms_names.";
22 std::string zone_group_info_oid_prefix
= "zonegroup_info.";
23 std::string realm_info_oid_prefix
= "realms.";
24 std::string default_region_info_oid
= "default.region";
25 std::string default_zone_group_info_oid
= "default.zonegroup";
26 std::string period_info_oid_prefix
= "periods.";
27 std::string period_latest_epoch_info_oid
= ".latest_epoch";
28 std::string region_map_oid
= "region_map";
29 std::string default_realm_info_oid
= "default.realm";
30 std::string default_zonegroup_name
= "default";
31 std::string default_zone_name
= "default";
32 std::string zonegroup_names_oid_prefix
= "zonegroups_names.";
33 std::string RGW_DEFAULT_ZONE_ROOT_POOL
= "rgw.root";
34 std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL
= "rgw.root";
35 std::string RGW_DEFAULT_REALM_ROOT_POOL
= "rgw.root";
36 std::string RGW_DEFAULT_PERIOD_ROOT_POOL
= "rgw.root";
37 std::string default_bucket_index_pool_suffix
= "rgw.buckets.index";
38 std::string default_storage_extra_pool_suffix
= "rgw.buckets.non-ec";
39 std::string avail_pools
= ".pools.avail";
40 std::string default_storage_pool_suffix
= "rgw.buckets.data";
44 using namespace rgw_zone_defaults
;
48 void RGWDefaultZoneGroupInfo::dump(Formatter
*f
) const {
49 encode_json("default_zonegroup", default_zonegroup
, f
);
52 void RGWDefaultZoneGroupInfo::decode_json(JSONObj
*obj
) {
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
);
61 rgw_pool
RGWZoneGroup::get_pool(CephContext
*cct_
) const
63 if (cct_
->_conf
->rgw_zonegroup_root_pool
.empty()) {
64 return rgw_pool(RGW_DEFAULT_ZONEGROUP_ROOT_POOL
);
67 return rgw_pool(cct_
->_conf
->rgw_zonegroup_root_pool
);
70 int RGWZoneGroup::create_default(const DoutPrefixProvider
*dpp
, optional_yield y
, bool old_format
)
72 name
= default_zonegroup_name
;
73 api_name
= default_zonegroup_name
;
76 RGWZoneGroupPlacementTarget placement_target
;
77 placement_target
.name
= "default-placement";
78 placement_targets
[placement_target
.name
] = placement_target
;
79 default_placement
.name
= "default-placement";
81 RGWZoneParams
zone_params(default_zone_name
);
83 int r
= zone_params
.init(dpp
, cct
, sysobj_svc
, y
, false);
85 ldpp_dout(dpp
, 0) << "create_default: error initializing zone params: " << cpp_strerror(-r
) << dendl
;
89 r
= zone_params
.create_default(dpp
, y
);
90 if (r
< 0 && r
!= -EEXIST
) {
91 ldpp_dout(dpp
, 0) << "create_default: error in create_default zone params: " << cpp_strerror(-r
) << dendl
;
93 } else if (r
== -EEXIST
) {
94 ldpp_dout(dpp
, 10) << "zone_params::create_default() returned -EEXIST, we raced with another default zone_params creation" << dendl
;
95 zone_params
.clear_id();
96 r
= zone_params
.init(dpp
, cct
, sysobj_svc
, y
);
98 ldpp_dout(dpp
, 0) << "create_default: error in init existing zone params: " << cpp_strerror(-r
) << dendl
;
101 ldpp_dout(dpp
, 20) << "zone_params::create_default() " << zone_params
.get_name() << " id " << zone_params
.get_id()
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
;
111 if (r
< 0 && r
!= -EEXIST
) {
112 ldpp_dout(dpp
, 0) << "error storing zone group info: " << cpp_strerror(-r
) << dendl
;
117 ldpp_dout(dpp
, 10) << "create_default() returned -EEXIST, we raced with another zonegroup creation" << dendl
;
119 r
= init(dpp
, cct
, sysobj_svc
, y
);
129 post_process_params(dpp
, y
);
134 const string
RGWZoneGroup::get_default_oid(bool old_region_format
) const
136 if (old_region_format
) {
137 if (cct
->_conf
->rgw_default_region_info_oid
.empty()) {
138 return default_region_info_oid
;
140 return cct
->_conf
->rgw_default_region_info_oid
;
143 string default_oid
= cct
->_conf
->rgw_default_zonegroup_info_oid
;
145 if (cct
->_conf
->rgw_default_zonegroup_info_oid
.empty()) {
146 default_oid
= default_zone_group_info_oid
;
149 default_oid
+= "." + realm_id
;
154 const string
& RGWZoneGroup::get_info_oid_prefix(bool old_region_format
) const
156 if (old_region_format
) {
157 return region_info_oid_prefix
;
159 return zone_group_info_oid_prefix
;
162 const string
& RGWZoneGroup::get_names_oid_prefix() const
164 return zonegroup_names_oid_prefix
;
167 const string
& RGWZoneGroup::get_predefined_name(CephContext
*cct
) const {
168 return cct
->_conf
->rgw_zonegroup
;
171 int RGWZoneGroup::equals(const string
& other_zonegroup
) const
173 if (is_master
&& other_zonegroup
.empty())
176 return (id
== other_zonegroup
);
179 int RGWZoneGroup::add_zone(const DoutPrefixProvider
*dpp
,
180 const RGWZoneParams
& zone_params
, bool *is_master
, bool *read_only
,
181 const list
<string
>& endpoints
, const string
*ptier_type
,
182 bool *psync_from_all
, list
<string
>& sync_from
, list
<string
>& sync_from_rm
,
183 string
*predirect_zone
, std::optional
<int> bucket_index_max_shards
,
184 RGWSyncModulesManager
*sync_mgr
,
187 auto& zone_id
= zone_params
.get_id();
188 auto& zone_name
= zone_params
.get_name();
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
) {
194 ldpp_dout(dpp
, 0) << "ERROR: found existing zone name " << zone_name
195 << " (" << zone
.first
<< ") in zonegroup " << get_name() << dendl
;
203 if (!master_zone
.empty() && master_zone
!= zone_id
) {
204 ldpp_dout(dpp
, 0) << "NOTICE: overriding master zone: " << master_zone
<< dendl
;
206 master_zone
= zone_id
;
207 } else if (master_zone
== zone_id
) {
212 RGWZone
& zone
= zones
[zone_id
];
213 zone
.name
= zone_name
;
215 if (!endpoints
.empty()) {
216 zone
.endpoints
= endpoints
;
219 zone
.read_only
= *read_only
;
222 zone
.tier_type
= *ptier_type
;
223 if (!sync_mgr
->get_module(*ptier_type
, nullptr)) {
224 ldpp_dout(dpp
, 0) << "ERROR: could not found sync module: " << *ptier_type
225 << ", valid sync modules: "
226 << sync_mgr
->get_registered_module_names()
232 if (psync_from_all
) {
233 zone
.sync_from_all
= *psync_from_all
;
236 if (predirect_zone
) {
237 zone
.redirect_zone
= *predirect_zone
;
240 if (bucket_index_max_shards
) {
241 zone
.bucket_index_max_shards
= *bucket_index_max_shards
;
244 for (auto add
: sync_from
) {
245 zone
.sync_from
.insert(add
);
248 for (auto rm
: sync_from_rm
) {
249 zone
.sync_from
.erase(rm
);
252 post_process_params(dpp
, y
);
254 return update(dpp
,y
);
258 int RGWZoneGroup::rename_zone(const DoutPrefixProvider
*dpp
,
259 const RGWZoneParams
& zone_params
,
262 RGWZone
& zone
= zones
[zone_params
.get_id()];
263 zone
.name
= zone_params
.get_name();
265 return update(dpp
, y
);
268 void RGWZoneGroup::post_process_params(const DoutPrefixProvider
*dpp
, optional_yield y
)
270 bool log_data
= zones
.size() > 1;
272 if (master_zone
.empty()) {
273 auto iter
= zones
.begin();
274 if (iter
!= zones
.end()) {
275 master_zone
= iter
->first
;
279 for (auto& item
: zones
) {
280 RGWZone
& zone
= item
.second
;
281 zone
.log_data
= log_data
;
283 RGWZoneParams
zone_params(zone
.id
, zone
.name
);
284 int ret
= zone_params
.init(dpp
, cct
, sysobj_svc
, y
);
286 ldpp_dout(dpp
, 0) << "WARNING: could not read zone params for zone id=" << zone
.id
<< " name=" << zone
.name
<< dendl
;
290 for (auto& pitem
: zone_params
.placement_pools
) {
291 const string
& placement_name
= pitem
.first
;
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
;
300 if (default_placement
.empty() && !placement_targets
.empty()) {
301 default_placement
.init(placement_targets
.begin()->first
, RGW_STORAGE_CLASS_STANDARD
);
305 int RGWZoneGroup::remove_zone(const DoutPrefixProvider
*dpp
, const std::string
& zone_id
, optional_yield y
)
307 auto iter
= zones
.find(zone_id
);
308 if (iter
== zones
.end()) {
309 ldpp_dout(dpp
, 0) << "zone id " << zone_id
<< " is not a part of zonegroup "
316 post_process_params(dpp
, y
);
318 return update(dpp
, y
);
321 int RGWZoneGroup::read_default_id(const DoutPrefixProvider
*dpp
, string
& default_id
, optional_yield y
,
324 if (realm_id
.empty()) {
325 /* try using default realm */
327 int ret
= realm
.init(dpp
, cct
, sysobj_svc
, y
);
328 // no default realm exist
330 return read_id(dpp
, default_zonegroup_name
, default_id
, y
);
332 realm_id
= realm
.get_id();
335 return RGWSystemMetaObj::read_default_id(dpp
, default_id
, y
, old_format
);
338 int RGWZoneGroup::set_as_default(const DoutPrefixProvider
*dpp
, optional_yield y
, bool exclusive
)
340 if (realm_id
.empty()) {
341 /* try using default realm */
343 int ret
= realm
.init(dpp
, cct
, sysobj_svc
, y
);
345 ldpp_dout(dpp
, 10) << "could not read realm id: " << cpp_strerror(-ret
) << dendl
;
348 realm_id
= realm
.get_id();
351 return RGWSystemMetaObj::set_as_default(dpp
, y
, exclusive
);
354 void RGWSystemMetaObj::reinit_instance(CephContext
*_cct
, RGWSI_SysObj
*_sysobj_svc
)
357 sysobj_svc
= _sysobj_svc
;
358 zone_svc
= _sysobj_svc
->get_zone_svc();
361 int RGWSystemMetaObj::init(const DoutPrefixProvider
*dpp
, CephContext
*_cct
, RGWSI_SysObj
*_sysobj_svc
,
363 bool setup_obj
, bool old_format
)
365 reinit_instance(_cct
, _sysobj_svc
);
370 if (old_format
&& id
.empty()) {
377 name
= get_predefined_name(cct
);
380 r
= use_default(dpp
, y
, old_format
);
384 } else if (!old_format
) {
385 r
= read_id(dpp
, name
, id
, y
);
388 ldpp_dout(dpp
, 0) << "error in read_id for object name: " << name
<< " : " << cpp_strerror(-r
) << dendl
;
395 return read_info(dpp
, id
, y
, old_format
);
398 int RGWSystemMetaObj::read_default(const DoutPrefixProvider
*dpp
,
399 RGWDefaultSystemMetaObjInfo
& default_info
,
400 const string
& oid
, optional_yield y
)
403 auto pool
= get_pool(cct
);
406 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
407 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj(pool
, oid
));
408 int ret
= sysobj
.rop().read(dpp
, &bl
, y
);
413 auto iter
= bl
.cbegin();
414 decode(default_info
, iter
);
415 } catch (buffer::error
& err
) {
416 ldpp_dout(dpp
, 0) << "error decoding data from " << pool
<< ":" << oid
<< dendl
;
423 int RGWSystemMetaObj::read_default_id(const DoutPrefixProvider
*dpp
, string
& default_id
, optional_yield y
,
426 RGWDefaultSystemMetaObjInfo default_info
;
428 int ret
= read_default(dpp
, default_info
, get_default_oid(old_format
), y
);
433 default_id
= default_info
.default_id
;
438 int RGWSystemMetaObj::use_default(const DoutPrefixProvider
*dpp
, optional_yield y
, bool old_format
)
440 return read_default_id(dpp
, id
, y
, old_format
);
443 int RGWSystemMetaObj::set_as_default(const DoutPrefixProvider
*dpp
, optional_yield y
, bool exclusive
)
446 string oid
= get_default_oid();
448 rgw_pool
pool(get_pool(cct
));
451 RGWDefaultSystemMetaObjInfo default_info
;
452 default_info
.default_id
= id
;
454 encode(default_info
, bl
);
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
)
467 int RGWSystemMetaObj::read_id(const DoutPrefixProvider
*dpp
, const string
& obj_name
, string
& object_id
,
471 rgw_pool
pool(get_pool(cct
));
474 string oid
= get_names_oid_prefix() + obj_name
;
476 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
477 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj(pool
, oid
));
478 int ret
= sysobj
.rop().read(dpp
, &bl
, y
);
483 RGWNameToId nameToId
;
485 auto iter
= bl
.cbegin();
486 decode(nameToId
, iter
);
487 } catch (buffer::error
& err
) {
488 ldpp_dout(dpp
, 0) << "ERROR: failed to decode obj from " << pool
<< ":" << oid
<< dendl
;
491 object_id
= nameToId
.obj_id
;
495 int RGWSystemMetaObj::delete_obj(const DoutPrefixProvider
*dpp
, optional_yield y
, bool old_format
)
497 rgw_pool
pool(get_pool(cct
));
499 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
501 /* check to see if obj is the default */
502 RGWDefaultSystemMetaObjInfo default_info
;
503 int ret
= read_default(dpp
, default_info
, get_default_oid(old_format
), y
);
504 if (ret
< 0 && ret
!= -ENOENT
)
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
);
510 ret
= sysobj
.wop().remove(dpp
, y
);
512 ldpp_dout(dpp
, 0) << "Error delete default obj name " << name
<< ": " << cpp_strerror(-ret
) << dendl
;
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
);
520 ret
= sysobj
.wop().remove(dpp
, y
);
522 ldpp_dout(dpp
, 0) << "Error delete obj name " << name
<< ": " << cpp_strerror(-ret
) << dendl
;
527 string oid
= get_info_oid_prefix(old_format
);
534 rgw_raw_obj
object_id(pool
, oid
);
535 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, object_id
);
536 ret
= sysobj
.wop().remove(dpp
, y
);
538 ldpp_dout(dpp
, 0) << "Error delete object id " << id
<< ": " << cpp_strerror(-ret
) << dendl
;
544 int RGWSystemMetaObj::store_name(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
546 rgw_pool
pool(get_pool(cct
));
547 string oid
= get_names_oid_prefix() + name
;
549 RGWNameToId nameToId
;
550 nameToId
.obj_id
= id
;
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
));
558 .set_exclusive(exclusive
)
562 int RGWSystemMetaObj::rename(const DoutPrefixProvider
*dpp
, const string
& new_name
, optional_yield y
)
565 int ret
= read_id(dpp
, new_name
, new_id
, y
);
569 if (ret
< 0 && ret
!= -ENOENT
) {
570 ldpp_dout(dpp
, 0) << "Error read_id " << new_name
<< ": " << cpp_strerror(-ret
) << dendl
;
573 string old_name
= name
;
575 ret
= update(dpp
, y
);
577 ldpp_dout(dpp
, 0) << "Error storing new obj info " << new_name
<< ": " << cpp_strerror(-ret
) << dendl
;
580 ret
= store_name(dpp
, true, y
);
582 ldpp_dout(dpp
, 0) << "Error storing new name " << new_name
<< ": " << cpp_strerror(-ret
) << dendl
;
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
);
591 ret
= sysobj
.wop().remove(dpp
, y
);
593 ldpp_dout(dpp
, 0) << "Error delete old obj name " << old_name
<< ": " << cpp_strerror(-ret
) << dendl
;
600 int RGWSystemMetaObj::read_info(const DoutPrefixProvider
*dpp
, const string
& obj_id
, optional_yield y
,
603 rgw_pool
pool(get_pool(cct
));
607 string oid
= get_info_oid_prefix(old_format
) + obj_id
;
609 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
610 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj
{pool
, oid
});
611 int ret
= sysobj
.rop().read(dpp
, &bl
, y
);
613 ldpp_dout(dpp
, 0) << "failed reading obj info from " << pool
<< ":" << oid
<< ": " << cpp_strerror(-ret
) << dendl
;
619 auto iter
= bl
.cbegin();
621 } catch (buffer::error
& err
) {
622 ldpp_dout(dpp
, 0) << "ERROR: failed to decode obj from " << pool
<< ":" << oid
<< dendl
;
629 int RGWSystemMetaObj::read(const DoutPrefixProvider
*dpp
, optional_yield y
)
631 int ret
= read_id(dpp
, name
, id
, y
);
636 return read_info(dpp
, id
, y
);
639 int RGWSystemMetaObj::create(const DoutPrefixProvider
*dpp
, optional_yield y
, bool exclusive
)
643 /* check to see the name is not used */
644 ret
= read_id(dpp
, name
, id
, y
);
645 if (exclusive
&& ret
== 0) {
646 ldpp_dout(dpp
, 10) << "ERROR: name " << name
<< " already in use for obj id " << id
<< dendl
;
648 } else if ( ret
< 0 && ret
!= -ENOENT
) {
649 ldpp_dout(dpp
, 0) << "failed reading obj id " << id
<< ": " << cpp_strerror(-ret
) << dendl
;
654 /* create unique id */
657 new_uuid
.generate_random();
658 new_uuid
.print(uuid_str
);
662 ret
= store_info(dpp
, exclusive
, y
);
664 ldpp_dout(dpp
, 0) << "ERROR: storing info for " << id
<< ": " << cpp_strerror(-ret
) << dendl
;
668 return store_name(dpp
, exclusive
, y
);
671 int RGWSystemMetaObj::store_info(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
673 rgw_pool
pool(get_pool(cct
));
675 string oid
= get_info_oid_prefix() + id
;
680 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
681 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj
{pool
, oid
});
683 .set_exclusive(exclusive
)
687 int RGWSystemMetaObj::write(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
689 int ret
= store_info(dpp
, exclusive
, y
);
691 ldpp_dout(dpp
, 20) << __func__
<< "(): store_info() returned ret=" << ret
<< dendl
;
694 ret
= store_name(dpp
, exclusive
, y
);
696 ldpp_dout(dpp
, 20) << __func__
<< "(): store_name() returned ret=" << ret
<< dendl
;
703 const string
& RGWRealm::get_predefined_name(CephContext
*cct
) const {
704 return cct
->_conf
->rgw_realm
;
707 int RGWRealm::create(const DoutPrefixProvider
*dpp
, optional_yield y
, bool exclusive
)
709 int ret
= RGWSystemMetaObj::create(dpp
, y
, exclusive
);
711 ldpp_dout(dpp
, 0) << "ERROR creating new realm object " << name
<< ": " << cpp_strerror(-ret
) << dendl
;
714 // create the control object for watch/notify
715 ret
= create_control(dpp
, exclusive
, y
);
717 ldpp_dout(dpp
, 0) << "ERROR creating control for new realm " << name
<< ": " << cpp_strerror(-ret
) << dendl
;
721 if (current_period
.empty()) {
722 /* create new period for the realm */
723 ret
= period
.init(dpp
, cct
, sysobj_svc
, id
, y
, name
, false);
727 ret
= period
.create(dpp
, y
, true);
729 ldpp_dout(dpp
, 0) << "ERROR: creating new period for realm " << name
<< ": " << cpp_strerror(-ret
) << dendl
;
733 period
= RGWPeriod(current_period
, 0);
734 int ret
= period
.init(dpp
, cct
, sysobj_svc
, id
, y
, name
);
736 ldpp_dout(dpp
, 0) << "ERROR: failed to init period " << current_period
<< dendl
;
740 ret
= set_current_period(dpp
, period
, y
);
742 ldpp_dout(dpp
, 0) << "ERROR: failed set current period " << current_period
<< dendl
;
745 // try to set as default. may race with another create, so pass exclusive=true
746 // so we don't override an existing default
747 ret
= set_as_default(dpp
, y
, true);
748 if (ret
< 0 && ret
!= -EEXIST
) {
749 ldpp_dout(dpp
, 0) << "WARNING: failed to set realm as default realm, ret=" << ret
<< dendl
;
755 int RGWRealm::delete_obj(const DoutPrefixProvider
*dpp
, optional_yield y
)
757 int ret
= RGWSystemMetaObj::delete_obj(dpp
, y
);
761 return delete_control(dpp
, y
);
764 int RGWRealm::create_control(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
766 auto pool
= rgw_pool
{get_pool(cct
)};
767 auto oid
= get_control_oid();
769 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
770 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj
{pool
, oid
});
772 .set_exclusive(exclusive
)
776 int RGWRealm::delete_control(const DoutPrefixProvider
*dpp
, optional_yield y
)
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
);
782 return sysobj
.wop().remove(dpp
, y
);
785 rgw_pool
RGWRealm::get_pool(CephContext
*cct
) const
787 if (cct
->_conf
->rgw_realm_root_pool
.empty()) {
788 return rgw_pool(RGW_DEFAULT_REALM_ROOT_POOL
);
790 return rgw_pool(cct
->_conf
->rgw_realm_root_pool
);
793 const string
RGWRealm::get_default_oid(bool old_format
) const
795 if (cct
->_conf
->rgw_default_realm_info_oid
.empty()) {
796 return default_realm_info_oid
;
798 return cct
->_conf
->rgw_default_realm_info_oid
;
801 const string
& RGWRealm::get_names_oid_prefix() const
803 return realm_names_oid_prefix
;
806 const string
& RGWRealm::get_info_oid_prefix(bool old_format
) const
808 return realm_info_oid_prefix
;
811 int RGWRealm::set_current_period(const DoutPrefixProvider
*dpp
, RGWPeriod
& period
, optional_yield y
)
813 // update realm epoch to match the period's
814 if (epoch
> period
.get_realm_epoch()) {
815 ldpp_dout(dpp
, 0) << "ERROR: set_current_period with old realm epoch "
816 << period
.get_realm_epoch() << ", current epoch=" << epoch
<< dendl
;
819 if (epoch
== period
.get_realm_epoch() && current_period
!= period
.get_id()) {
820 ldpp_dout(dpp
, 0) << "ERROR: set_current_period with same realm epoch "
821 << period
.get_realm_epoch() << ", but different period id "
822 << period
.get_id() << " != " << current_period
<< dendl
;
826 epoch
= period
.get_realm_epoch();
827 current_period
= period
.get_id();
829 int ret
= update(dpp
, y
);
831 ldpp_dout(dpp
, 0) << "ERROR: period update: " << cpp_strerror(-ret
) << dendl
;
835 ret
= period
.reflect(dpp
, y
);
837 ldpp_dout(dpp
, 0) << "ERROR: period.reflect(): " << cpp_strerror(-ret
) << dendl
;
844 string
RGWRealm::get_control_oid() const
846 return get_info_oid_prefix() + id
+ ".control";
849 int RGWRealm::notify_zone(const DoutPrefixProvider
*dpp
, bufferlist
& bl
, optional_yield y
)
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()});
854 int ret
= sysobj
.wn().notify(dpp
, bl
, 0, nullptr, y
);
861 int RGWRealm::notify_new_period(const DoutPrefixProvider
*dpp
, const RGWPeriod
& period
, optional_yield y
)
865 // push the period to dependent zonegroups/zones
866 encode(RGWRealmNotify::ZonesNeedPeriod
, bl
);
868 // reload the gateway with the new period
869 encode(RGWRealmNotify::Reload
, bl
);
871 return notify_zone(dpp
, bl
, y
);
874 std::string
RGWPeriodConfig::get_oid(const std::string
& realm_id
)
876 if (realm_id
.empty()) {
877 return "period_config.default";
879 return "period_config." + realm_id
;
882 rgw_pool
RGWPeriodConfig::get_pool(CephContext
*cct
)
884 const auto& pool_name
= cct
->_conf
->rgw_period_root_pool
;
885 if (pool_name
.empty()) {
886 return {RGW_DEFAULT_PERIOD_ROOT_POOL
};
891 int RGWPeriodConfig::read(const DoutPrefixProvider
*dpp
, RGWSI_SysObj
*sysobj_svc
, const std::string
& realm_id
,
894 const auto& pool
= get_pool(sysobj_svc
->ctx());
895 const auto& oid
= get_oid(realm_id
);
898 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
899 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj
{pool
, oid
});
900 int ret
= sysobj
.rop().read(dpp
, &bl
, y
);
906 auto iter
= bl
.cbegin();
908 } catch (buffer::error
& err
) {
914 int RGWPeriodConfig::write(const DoutPrefixProvider
*dpp
,
915 RGWSI_SysObj
*sysobj_svc
,
916 const std::string
& realm_id
, optional_yield y
)
918 const auto& pool
= get_pool(sysobj_svc
->ctx());
919 const auto& oid
= get_oid(realm_id
);
923 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
924 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj
{pool
, oid
});
926 .set_exclusive(false)
930 int RGWPeriod::init(const DoutPrefixProvider
*dpp
, CephContext
*_cct
, RGWSI_SysObj
*_sysobj_svc
,
931 const string
& period_realm_id
, optional_yield y
,
932 const string
& period_realm_name
, bool setup_obj
)
935 sysobj_svc
= _sysobj_svc
;
937 realm_id
= period_realm_id
;
938 realm_name
= period_realm_name
;
943 return init(dpp
, _cct
, _sysobj_svc
, y
, setup_obj
);
947 int RGWPeriod::init(const DoutPrefixProvider
*dpp
,
948 CephContext
*_cct
, RGWSI_SysObj
*_sysobj_svc
,
949 optional_yield y
, bool setup_obj
)
952 sysobj_svc
= _sysobj_svc
;
958 RGWRealm
realm(realm_id
, realm_name
);
959 int ret
= realm
.init(dpp
, cct
, sysobj_svc
, y
);
961 ldpp_dout(dpp
, 0) << "RGWPeriod::init failed to init realm " << realm_name
<< " id " << realm_id
<< " : " <<
962 cpp_strerror(-ret
) << dendl
;
965 id
= realm
.get_current_period();
966 realm_id
= realm
.get_id();
970 int ret
= use_latest_epoch(dpp
, y
);
972 ldpp_dout(dpp
, 0) << "failed to use_latest_epoch period id " << id
<< " realm " << realm_name
<< " id " << realm_id
973 << " : " << cpp_strerror(-ret
) << dendl
;
978 return read_info(dpp
, y
);
982 int RGWPeriod::get_zonegroup(RGWZoneGroup
& zonegroup
,
983 const string
& zonegroup_id
) const
985 map
<string
, RGWZoneGroup
>::const_iterator iter
;
986 if (!zonegroup_id
.empty()) {
987 iter
= period_map
.zonegroups
.find(zonegroup_id
);
989 iter
= period_map
.zonegroups
.find("default");
991 if (iter
!= period_map
.zonegroups
.end()) {
992 zonegroup
= iter
->second
;
999 const string
& RGWPeriod::get_latest_epoch_oid() const
1001 if (cct
->_conf
->rgw_period_latest_epoch_info_oid
.empty()) {
1002 return period_latest_epoch_info_oid
;
1004 return cct
->_conf
->rgw_period_latest_epoch_info_oid
;
1007 const string
& RGWPeriod::get_info_oid_prefix() const
1009 return period_info_oid_prefix
;
1012 const string
RGWPeriod::get_period_oid_prefix() const
1014 return get_info_oid_prefix() + id
;
1017 const string
RGWPeriod::get_period_oid() const
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
;
1027 int RGWPeriod::read_latest_epoch(const DoutPrefixProvider
*dpp
,
1028 RGWPeriodLatestEpochInfo
& info
,
1030 RGWObjVersionTracker
*objv
)
1032 string oid
= get_period_oid_prefix() + get_latest_epoch_oid();
1034 rgw_pool
pool(get_pool(cct
));
1036 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1037 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj
{pool
, oid
});
1038 int ret
= sysobj
.rop().read(dpp
, &bl
, y
);
1040 ldpp_dout(dpp
, 1) << "error read_lastest_epoch " << pool
<< ":" << oid
<< dendl
;
1044 auto iter
= bl
.cbegin();
1047 } catch (buffer::error
& err
) {
1048 ldpp_dout(dpp
, 0) << "error decoding data from " << pool
<< ":" << oid
<< dendl
;
1055 int RGWPeriod::get_latest_epoch(const DoutPrefixProvider
*dpp
, epoch_t
& latest_epoch
, optional_yield y
)
1057 RGWPeriodLatestEpochInfo info
;
1059 int ret
= read_latest_epoch(dpp
, info
, y
);
1064 latest_epoch
= info
.epoch
;
1069 int RGWPeriod::use_latest_epoch(const DoutPrefixProvider
*dpp
, optional_yield y
)
1071 RGWPeriodLatestEpochInfo info
;
1072 int ret
= read_latest_epoch(dpp
, info
, y
);
1082 int RGWPeriod::set_latest_epoch(const DoutPrefixProvider
*dpp
,
1084 epoch_t epoch
, bool exclusive
,
1085 RGWObjVersionTracker
*objv
)
1087 string oid
= get_period_oid_prefix() + get_latest_epoch_oid();
1089 rgw_pool
pool(get_pool(cct
));
1092 RGWPeriodLatestEpochInfo info
;
1098 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1099 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj(pool
, oid
));
1101 .set_exclusive(exclusive
)
1105 int RGWPeriod::update_latest_epoch(const DoutPrefixProvider
*dpp
, epoch_t epoch
, optional_yield y
)
1107 static constexpr int MAX_RETRIES
= 20;
1109 for (int i
= 0; i
< MAX_RETRIES
; i
++) {
1110 RGWPeriodLatestEpochInfo info
;
1111 RGWObjVersionTracker objv
;
1112 bool exclusive
= false;
1114 // read existing epoch
1115 int r
= read_latest_epoch(dpp
, info
, y
, &objv
);
1117 // use an exclusive create to set the epoch atomically
1119 ldpp_dout(dpp
, 20) << "creating initial latest_epoch=" << epoch
1120 << " for period=" << id
<< dendl
;
1122 ldpp_dout(dpp
, 0) << "ERROR: failed to read latest_epoch" << dendl
;
1124 } else if (epoch
<= info
.epoch
) {
1125 r
= -EEXIST
; // fail with EEXIST if epoch is not newer
1126 ldpp_dout(dpp
, 10) << "found existing latest_epoch " << info
.epoch
1127 << " >= given epoch " << epoch
<< ", returning r=" << r
<< dendl
;
1130 ldpp_dout(dpp
, 20) << "updating latest_epoch from " << info
.epoch
1131 << " -> " << epoch
<< " on period=" << id
<< dendl
;
1134 r
= set_latest_epoch(dpp
, y
, epoch
, exclusive
, &objv
);
1136 continue; // exclusive create raced with another update, retry
1137 } else if (r
== -ECANCELED
) {
1138 continue; // write raced with a conflicting version, retry
1141 ldpp_dout(dpp
, 0) << "ERROR: failed to write latest_epoch" << dendl
;
1144 return 0; // return success
1147 return -ECANCELED
; // fail after max retries
1150 int RGWPeriod::delete_obj(const DoutPrefixProvider
*dpp
, optional_yield y
)
1152 rgw_pool
pool(get_pool(cct
));
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
);
1160 int ret
= sysobj
.wop().remove(dpp
, y
);
1162 ldpp_dout(dpp
, 0) << "WARNING: failed to delete period object " << oid
1163 << ": " << cpp_strerror(-ret
) << dendl
;
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
);
1171 int ret
= sysobj
.wop().remove(dpp
, y
);
1173 ldpp_dout(dpp
, 0) << "WARNING: failed to delete period object " << oid
1174 << ": " << cpp_strerror(-ret
) << dendl
;
1179 int RGWPeriod::read_info(const DoutPrefixProvider
*dpp
, optional_yield y
)
1181 rgw_pool
pool(get_pool(cct
));
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()});
1187 int ret
= sysobj
.rop().read(dpp
, &bl
, y
);
1189 ldpp_dout(dpp
, 0) << "failed reading obj info from " << pool
<< ":" << get_period_oid() << ": " << cpp_strerror(-ret
) << dendl
;
1195 auto iter
= bl
.cbegin();
1196 decode(*this, iter
);
1197 } catch (buffer::error
& err
) {
1198 ldpp_dout(dpp
, 0) << "ERROR: failed to decode obj from " << pool
<< ":" << get_period_oid() << dendl
;
1205 int RGWPeriod::create(const DoutPrefixProvider
*dpp
, optional_yield y
, bool exclusive
)
1209 /* create unique id */
1212 new_uuid
.generate_random();
1213 new_uuid
.print(uuid_str
);
1216 epoch
= FIRST_EPOCH
;
1220 ret
= store_info(dpp
, exclusive
, y
);
1222 ldpp_dout(dpp
, 0) << "ERROR: storing info for " << id
<< ": " << cpp_strerror(-ret
) << dendl
;
1226 ret
= set_latest_epoch(dpp
, y
, epoch
);
1228 ldpp_dout(dpp
, 0) << "ERROR: setting latest epoch " << id
<< ": " << cpp_strerror(-ret
) << dendl
;
1234 int RGWPeriod::store_info(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
1236 rgw_pool
pool(get_pool(cct
));
1238 string oid
= get_period_oid();
1243 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1244 auto sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj(pool
, oid
));
1246 .set_exclusive(exclusive
)
1250 rgw_pool
RGWPeriod::get_pool(CephContext
*cct
) const
1252 if (cct
->_conf
->rgw_period_root_pool
.empty()) {
1253 return rgw_pool(RGW_DEFAULT_PERIOD_ROOT_POOL
);
1255 return rgw_pool(cct
->_conf
->rgw_period_root_pool
);
1258 int RGWPeriod::add_zonegroup(const DoutPrefixProvider
*dpp
, const RGWZoneGroup
& zonegroup
, optional_yield y
)
1260 if (zonegroup
.realm_id
!= realm_id
) {
1263 int ret
= period_map
.update(zonegroup
, cct
);
1265 ldpp_dout(dpp
, 0) << "ERROR: updating period map: " << cpp_strerror(-ret
) << dendl
;
1269 return store_info(dpp
, false, y
);
1272 int RGWPeriod::update(const DoutPrefixProvider
*dpp
, optional_yield y
)
1274 auto zone_svc
= sysobj_svc
->get_zone_svc();
1275 ldpp_dout(dpp
, 20) << __func__
<< " realm " << realm_id
<< " period " << get_id() << dendl
;
1276 list
<string
> zonegroups
;
1277 int ret
= zone_svc
->list_zonegroups(dpp
, zonegroups
);
1279 ldpp_dout(dpp
, 0) << "ERROR: failed to list zonegroups: " << cpp_strerror(-ret
) << dendl
;
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();
1287 for (auto& iter
: zonegroups
) {
1288 RGWZoneGroup
zg(string(), iter
);
1289 ret
= zg
.init(dpp
, cct
, sysobj_svc
, y
);
1291 ldpp_dout(dpp
, 0) << "WARNING: zg.init() failed: " << cpp_strerror(-ret
) << dendl
;
1295 if (zg
.realm_id
!= realm_id
) {
1296 ldpp_dout(dpp
, 20) << "skipping zonegroup " << zg
.get_name() << " zone realm id " << zg
.realm_id
<< ", not on our realm " << realm_id
<< dendl
;
1300 if (zg
.master_zone
.empty()) {
1301 ldpp_dout(dpp
, 0) << "ERROR: zonegroup " << zg
.get_name() << " should have a master zone " << dendl
;
1305 if (zg
.zones
.find(zg
.master_zone
) == zg
.zones
.end()) {
1306 ldpp_dout(dpp
, 0) << "ERROR: zonegroup " << zg
.get_name()
1307 << " has a non existent master zone "<< dendl
;
1311 if (zg
.is_master_zonegroup()) {
1312 master_zonegroup
= zg
.get_id();
1313 master_zone
= zg
.master_zone
;
1316 int ret
= period_map
.update(zg
, cct
);
1322 ret
= period_config
.read(dpp
, sysobj_svc
, realm_id
, y
);
1323 if (ret
< 0 && ret
!= -ENOENT
) {
1324 ldpp_dout(dpp
, 0) << "ERROR: failed to read period config: "
1325 << cpp_strerror(ret
) << dendl
;
1331 int RGWPeriod::reflect(const DoutPrefixProvider
*dpp
, optional_yield y
)
1333 for (auto& iter
: period_map
.zonegroups
) {
1334 RGWZoneGroup
& zg
= iter
.second
;
1335 zg
.reinit_instance(cct
, sysobj_svc
);
1336 int r
= zg
.write(dpp
, false, y
);
1338 ldpp_dout(dpp
, 0) << "ERROR: failed to store zonegroup info for zonegroup=" << iter
.first
<< ": " << cpp_strerror(-r
) << dendl
;
1341 if (zg
.is_master_zonegroup()) {
1342 // set master as default if no default exists
1343 r
= zg
.set_as_default(dpp
, y
, true);
1345 ldpp_dout(dpp
, 1) << "Set the period's master zonegroup " << zg
.get_id()
1346 << " as the default" << dendl
;
1351 int r
= period_config
.write(dpp
, sysobj_svc
, realm_id
, y
);
1353 ldpp_dout(dpp
, 0) << "ERROR: failed to store period config: "
1354 << cpp_strerror(-r
) << dendl
;
1360 void RGWPeriod::fork()
1362 ldout(cct
, 20) << __func__
<< " realm " << realm_id
<< " period " << id
<< dendl
;
1363 predecessor_uuid
= id
;
1364 id
= get_staging_id(realm_id
);
1369 static int read_sync_status(const DoutPrefixProvider
*dpp
, rgw::sal::RGWRadosStore
*store
, rgw_meta_sync_status
*sync_status
)
1371 // initialize a sync status manager to read the status
1372 RGWMetaSyncStatusManager
mgr(store
, store
->svc()->rados
->get_async_processor());
1373 int r
= mgr
.init(dpp
);
1377 r
= mgr
.read_sync_status(dpp
, sync_status
);
1382 int RGWPeriod::update_sync_status(const DoutPrefixProvider
*dpp
,
1383 rgw::sal::RGWRadosStore
*store
, /* for now */
1384 const RGWPeriod
¤t_period
,
1385 std::ostream
& error_stream
,
1386 bool force_if_stale
)
1388 rgw_meta_sync_status status
;
1389 int r
= read_sync_status(dpp
, store
, &status
);
1391 ldpp_dout(dpp
, 0) << "period failed to read sync status: "
1392 << cpp_strerror(-r
) << dendl
;
1396 std::vector
<std::string
> markers
;
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 "
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
;
1414 // empty sync status markers - other zones will skip this period during
1415 // incremental metadata sync
1416 markers
.resize(status
.sync_info
.num_shards
);
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();
1425 markers
.emplace_back(std::move(marker
.marker
));
1429 std::swap(sync_status
, markers
);
1433 int RGWPeriod::commit(const DoutPrefixProvider
*dpp
,
1434 rgw::sal::RGWRadosStore
*store
,
1435 RGWRealm
& realm
, const RGWPeriod
& current_period
,
1436 std::ostream
& error_stream
, optional_yield y
,
1437 bool force_if_stale
)
1439 auto zone_svc
= sysobj_svc
->get_zone_svc();
1440 ldpp_dout(dpp
, 20) << __func__
<< " realm " << realm
.get_id() << " period " << current_period
.get_id() << dendl
;
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
;
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
;
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
;
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
1468 int r
= update_sync_status(dpp
, store
, current_period
, error_stream
, force_if_stale
);
1470 ldpp_dout(dpp
, 0) << "failed to update metadata sync status: "
1471 << cpp_strerror(-r
) << dendl
;
1474 // create an object with a new period id
1475 r
= create(dpp
, y
, true);
1477 ldpp_dout(dpp
, 0) << "failed to create new period: " << cpp_strerror(-r
) << dendl
;
1480 // set as current period
1481 r
= realm
.set_current_period(dpp
, *this, y
);
1483 ldpp_dout(dpp
, 0) << "failed to update realm's current period: "
1484 << cpp_strerror(-r
) << dendl
;
1487 ldpp_dout(dpp
, 4) << "Promoted to master zone and committed new period "
1489 realm
.notify_new_period(dpp
, *this, y
);
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
;
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
1506 int r
= store_info(dpp
, false, y
);
1508 ldpp_dout(dpp
, 0) << "failed to store period: " << cpp_strerror(-r
) << dendl
;
1511 // set as latest epoch
1512 r
= update_latest_epoch(dpp
, epoch
, y
);
1514 // already have this epoch (or a more recent one)
1518 ldpp_dout(dpp
, 0) << "failed to set latest epoch: " << cpp_strerror(-r
) << dendl
;
1521 r
= reflect(dpp
, y
);
1523 ldpp_dout(dpp
, 0) << "failed to update local objects: " << cpp_strerror(-r
) << dendl
;
1526 ldpp_dout(dpp
, 4) << "Committed new epoch " << epoch
1527 << " for period " << id
<< dendl
;
1528 realm
.notify_new_period(dpp
, *this, y
);
1532 int RGWZoneParams::create_default(const DoutPrefixProvider
*dpp
, optional_yield y
, bool old_format
)
1534 name
= default_zone_name
;
1536 int r
= create(dpp
, y
);
1550 int get_zones_pool_set(const DoutPrefixProvider
*dpp
,
1552 RGWSI_SysObj
* sysobj_svc
,
1553 const list
<string
>& zones
,
1554 const string
& my_zone_id
,
1555 set
<rgw_pool
>& pool_names
,
1558 for(auto const& iter
: zones
) {
1559 RGWZoneParams
zone(iter
);
1560 int r
= zone
.init(dpp
, cct
, sysobj_svc
, y
);
1562 ldpp_dout(dpp
, 0) << "Error: init zone " << iter
<< ":" << cpp_strerror(-r
) << dendl
;
1565 if (zone
.get_id() != my_zone_id
) {
1566 pool_names
.insert(zone
.domain_root
);
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
);
1579 pool_names
.insert(zone
.notif_pool
);
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());
1587 pool_names
.insert(iter
.second
.data_extra_pool
);
1589 pool_names
.insert(zone
.oidc_pool
);
1595 rgw_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
)
1600 string suggested_name
= suggested_pool
.to_str();
1602 string prefix
= default_prefix
;
1603 string suffix
= default_suffix
;
1605 if (!suggested_pool
.empty()) {
1606 prefix
= suggested_name
.substr(0, suggested_name
.find("."));
1607 suffix
= suggested_name
.substr(prefix
.length());
1610 rgw_pool
pool(prefix
+ suffix
);
1612 if (pools
.find(pool
) == pools
.end()) {
1616 pool
= prefix
+ "_" + std::to_string(std::rand()) + suffix
;
1617 if (pools
.find(pool
) == pools
.end()) {
1625 int RGWZoneParams::fix_pool_names(const DoutPrefixProvider
*dpp
, optional_yield y
)
1629 int r
= zone_svc
->list_zones(dpp
, zones
);
1631 ldpp_dout(dpp
, 10) << "WARNING: store->list_zones() returned r=" << r
<< dendl
;
1634 set
<rgw_pool
> pools
;
1635 r
= get_zones_pool_set(dpp
, cct
, sysobj_svc
, zones
, id
, pools
, y
);
1637 ldpp_dout(dpp
, 0) << "Error: get_zones_pool_names" << r
<< dendl
;
1641 domain_root
= fix_zone_pool_dup(pools
, name
, ".rgw.meta:root", domain_root
);
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
);
1655 oidc_pool
= fix_zone_pool_dup(pools
, name
, ".rgw.meta:oidc", oidc_pool
);
1656 notif_pool
= fix_zone_pool_dup(pools
, name
,".rgw.log:notif", notif_pool
);
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
,
1668 iter
.second
.data_extra_pool
= fix_zone_pool_dup(pools
, name
, "." + default_storage_extra_pool_suffix
,
1669 iter
.second
.data_extra_pool
);
1675 int RGWZoneParams::create(const DoutPrefixProvider
*dpp
, optional_yield y
, bool exclusive
)
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
);
1681 int r
= sysobj
.rop().stat(y
, dpp
);
1683 ldpp_dout(dpp
, 10) << "couldn't find old data placement pools config, setting up new ones for the zone" << dendl
;
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
;
1693 r
= fix_pool_names(dpp
, y
);
1695 ldpp_dout(dpp
, 0) << "ERROR: fix_pool_names returned r=" << r
<< dendl
;
1699 r
= RGWSystemMetaObj::create(dpp
, y
, exclusive
);
1704 // try to set as default. may race with another create, so pass exclusive=true
1705 // so we don't override an existing default
1706 r
= set_as_default(dpp
, y
, true);
1707 if (r
< 0 && r
!= -EEXIST
) {
1708 ldpp_dout(dpp
, 10) << "WARNING: failed to set zone as default, r=" << r
<< dendl
;
1714 rgw_pool
RGWZoneParams::get_pool(CephContext
*cct
) const
1716 if (cct
->_conf
->rgw_zone_root_pool
.empty()) {
1717 return rgw_pool(RGW_DEFAULT_ZONE_ROOT_POOL
);
1720 return rgw_pool(cct
->_conf
->rgw_zone_root_pool
);
1723 const string
RGWZoneParams::get_default_oid(bool old_format
) const
1726 return cct
->_conf
->rgw_default_zone_info_oid
;
1729 return cct
->_conf
->rgw_default_zone_info_oid
+ "." + realm_id
;
1732 const string
& RGWZoneParams::get_names_oid_prefix() const
1734 return zone_names_oid_prefix
;
1737 const string
& RGWZoneParams::get_info_oid_prefix(bool old_format
) const
1739 return zone_info_oid_prefix
;
1742 const string
& RGWZoneParams::get_predefined_name(CephContext
*cct
) const {
1743 return cct
->_conf
->rgw_zone
;
1746 int RGWZoneParams::init(const DoutPrefixProvider
*dpp
,
1747 CephContext
*cct
, RGWSI_SysObj
*sysobj_svc
,
1748 optional_yield y
, bool setup_obj
, bool old_format
)
1751 name
= cct
->_conf
->rgw_zone
;
1754 return RGWSystemMetaObj::init(dpp
, cct
, sysobj_svc
, y
, setup_obj
, old_format
);
1757 int RGWZoneParams::read_default_id(const DoutPrefixProvider
*dpp
, string
& default_id
, optional_yield y
,
1760 if (realm_id
.empty()) {
1761 /* try using default realm */
1763 int ret
= realm
.init(dpp
, cct
, sysobj_svc
, y
);
1764 //no default realm exist
1766 return read_id(dpp
, default_zone_name
, default_id
, y
);
1768 realm_id
= realm
.get_id();
1771 return RGWSystemMetaObj::read_default_id(dpp
, default_id
, y
, old_format
);
1775 int RGWZoneParams::set_as_default(const DoutPrefixProvider
*dpp
, optional_yield y
, bool exclusive
)
1777 if (realm_id
.empty()) {
1778 /* try using default realm */
1780 int ret
= realm
.init(dpp
, cct
, sysobj_svc
, y
);
1782 ldpp_dout(dpp
, 10) << "could not read realm id: " << cpp_strerror(-ret
) << dendl
;
1785 realm_id
= realm
.get_id();
1788 return RGWSystemMetaObj::set_as_default(dpp
, y
, exclusive
);
1791 const string
& RGWZoneParams::get_compression_type(const rgw_placement_rule
& placement_rule
) const
1793 static const std::string NONE
{"none"};
1794 auto p
= placement_pools
.find(placement_rule
.name
);
1795 if (p
== placement_pools
.end()) {
1798 const auto& type
= p
->second
.get_compression_type(placement_rule
.get_storage_class());
1799 return !type
.empty() ? type
: NONE
;
1802 void RGWPeriodMap::encode(bufferlist
& bl
) const {
1803 ENCODE_START(2, 1, bl
);
1805 encode(zonegroups
, bl
);
1806 encode(master_zonegroup
, bl
);
1807 encode(short_zone_ids
, bl
);
1811 void RGWPeriodMap::decode(bufferlist::const_iterator
& bl
) {
1812 DECODE_START(2, bl
);
1814 decode(zonegroups
, bl
);
1815 decode(master_zonegroup
, bl
);
1816 if (struct_v
>= 2) {
1817 decode(short_zone_ids
, bl
);
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();
1832 // run an MD5 hash on the zone_id and return the first 32 bits
1833 static uint32_t gen_short_zone_id(const std::string zone_id
)
1835 unsigned char md5
[CEPH_CRYPTO_MD5_DIGESTSIZE
];
1837 hash
.Update((const unsigned char *)zone_id
.c_str(), zone_id
.size());
1841 memcpy((char *)&short_id
, md5
, sizeof(short_id
));
1842 return std::max(short_id
, 1u);
1845 int RGWPeriodMap::update(const RGWZoneGroup
& zonegroup
, CephContext
*cct
)
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
;
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
);
1859 zonegroups
[zonegroup
.get_id()] = zonegroup
;
1861 if (!zonegroup
.api_name
.empty()) {
1862 zonegroups_by_api
[zonegroup
.api_name
] = zonegroup
;
1865 if (zonegroup
.is_master_zonegroup()) {
1866 master_zonegroup
= zonegroup
.get_id();
1867 } else if (master_zonegroup
== zonegroup
.get_id()) {
1868 master_zonegroup
= "";
1871 for (auto& i
: zonegroup
.zones
) {
1872 auto& zone
= i
.second
;
1873 if (short_zone_ids
.find(zone
.id
) != short_zone_ids
.end()) {
1876 // calculate the zone's short id
1877 uint32_t short_id
= gen_short_zone_id(zone
.id
);
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
;
1889 short_zone_ids
[zone
.id
] = short_id
;
1895 uint32_t RGWPeriodMap::get_zone_short_id(const string
& zone_id
) const
1897 auto i
= short_zone_ids
.find(zone_id
);
1898 if (i
== short_zone_ids
.end()) {
1904 int RGWZoneGroupMap::read(const DoutPrefixProvider
*dpp
, CephContext
*cct
, RGWSI_SysObj
*sysobj_svc
, optional_yield y
)
1908 int ret
= period
.init(dpp
, cct
, sysobj_svc
, y
);
1910 cerr
<< "failed to read current period info: " << cpp_strerror(ret
);
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
;
1923 void 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
);
1932 void RGWRegionMap::decode(bufferlist::const_iterator
& bl
) {
1933 DECODE_START(3, bl
);
1934 decode(regions
, bl
);
1935 decode(master_region
, bl
);
1937 decode(bucket_quota
, bl
);
1939 decode(user_quota
, bl
);
1943 void 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
);
1952 void RGWZoneGroupMap::decode(bufferlist::const_iterator
& bl
) {
1953 DECODE_START(3, bl
);
1954 decode(zonegroups
, bl
);
1955 decode(master_zonegroup
, bl
);
1957 decode(bucket_quota
, bl
);
1959 decode(user_quota
, bl
);
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();