3 #include "svc_sys_obj.h"
4 #include "svc_sync_modules.h"
6 #include "rgw/rgw_zone.h"
7 #include "rgw/rgw_rest_conn.h"
9 #include "common/errno.h"
10 #include "include/random.h"
12 #define dout_subsys ceph_subsys_rgw
14 using namespace rgw_zone_defaults
;
16 RGWSI_Zone::RGWSI_Zone(CephContext
*cct
) : RGWServiceInstance(cct
)
20 void RGWSI_Zone::init(RGWSI_SysObj
*_sysobj_svc
,
21 RGWSI_RADOS
* _rados_svc
,
22 RGWSI_SyncModules
* _sync_modules_svc
)
24 sysobj_svc
= _sysobj_svc
;
25 rados_svc
= _rados_svc
;
26 sync_modules_svc
= _sync_modules_svc
;
28 realm
= new RGWRealm();
29 zonegroup
= new RGWZoneGroup();
30 zone_public_config
= new RGWZone();
31 zone_params
= new RGWZoneParams();
32 current_period
= new RGWPeriod();
35 RGWSI_Zone::~RGWSI_Zone()
39 delete zone_public_config
;
41 delete current_period
;
44 bool RGWSI_Zone::zone_syncs_from(const RGWZone
& target_zone
, const RGWZone
& source_zone
) const
46 return target_zone
.syncs_from(source_zone
.name
) &&
47 sync_modules_svc
->get_manager()->supports_data_export(source_zone
.tier_type
);
50 int RGWSI_Zone::do_start()
52 int ret
= sysobj_svc
->start();
57 assert(sysobj_svc
->is_started()); /* if not then there's ordering issue */
59 ret
= rados_svc
->start();
63 ret
= sync_modules_svc
->start();
67 ret
= realm
->init(cct
, sysobj_svc
);
68 if (ret
< 0 && ret
!= -ENOENT
) {
69 ldout(cct
, 0) << "failed reading realm info: ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
71 } else if (ret
!= -ENOENT
) {
72 ldout(cct
, 20) << "realm " << realm
->get_name() << " " << realm
->get_id() << dendl
;
73 ret
= current_period
->init(cct
, sysobj_svc
, realm
->get_id(), realm
->get_name());
74 if (ret
< 0 && ret
!= -ENOENT
) {
75 ldout(cct
, 0) << "failed reading current period info: " << " " << cpp_strerror(-ret
) << dendl
;
78 ldout(cct
, 20) << "current period " << current_period
->get_id() << dendl
;
81 ret
= replace_region_with_zonegroup();
83 lderr(cct
) << "failed converting region to zonegroup : ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
87 ret
= convert_regionmap();
89 lderr(cct
) << "failed converting regionmap: " << cpp_strerror(-ret
) << dendl
;
93 bool zg_initialized
= false;
95 if (!current_period
->get_id().empty()) {
96 ret
= init_zg_from_period(&zg_initialized
);
102 bool creating_defaults
= false;
103 bool using_local
= (!zg_initialized
);
105 ldout(cct
, 10) << " cannot find current period zonegroup using local zonegroup" << dendl
;
106 ret
= init_zg_from_local(&creating_defaults
);
110 // read period_config into current_period
111 auto& period_config
= current_period
->get_config();
112 ret
= period_config
.read(sysobj_svc
, zonegroup
->realm_id
);
113 if (ret
< 0 && ret
!= -ENOENT
) {
114 ldout(cct
, 0) << "ERROR: failed to read period config: "
115 << cpp_strerror(ret
) << dendl
;
120 ldout(cct
, 10) << "Cannot find current period zone using local zone" << dendl
;
121 if (creating_defaults
&& cct
->_conf
->rgw_zone
.empty()) {
122 ldout(cct
, 10) << " Using default name "<< default_zone_name
<< dendl
;
123 zone_params
->set_name(default_zone_name
);
126 ret
= zone_params
->init(cct
, sysobj_svc
);
127 if (ret
< 0 && ret
!= -ENOENT
) {
128 lderr(cct
) << "failed reading zone info: ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
131 auto zone_iter
= zonegroup
->zones
.find(zone_params
->get_id());
132 if (zone_iter
== zonegroup
->zones
.end()) {
134 lderr(cct
) << "Cannot find zone id=" << zone_params
->get_id() << " (name=" << zone_params
->get_name() << ")" << dendl
;
137 ldout(cct
, 1) << "Cannot find zone id=" << zone_params
->get_id() << " (name=" << zone_params
->get_name() << "), switching to local zonegroup configuration" << dendl
;
138 ret
= init_zg_from_local(&creating_defaults
);
142 zone_iter
= zonegroup
->zones
.find(zone_params
->get_id());
144 if (zone_iter
!= zonegroup
->zones
.end()) {
145 *zone_public_config
= zone_iter
->second
;
146 ldout(cct
, 20) << "zone " << zone_params
->get_name() << dendl
;
148 lderr(cct
) << "Cannot find zone id=" << zone_params
->get_id() << " (name=" << zone_params
->get_name() << ")" << dendl
;
152 zone_short_id
= current_period
->get_map().get_zone_short_id(zone_params
->get_id());
155 if (!sync_modules_svc
->get_manager()->get_module(zone_public_config
->tier_type
, &sm
)) {
156 lderr(cct
) << "ERROR: tier type not found: " << zone_public_config
->tier_type
<< dendl
;
160 writeable_zone
= sm
->supports_writes();
162 /* first build all zones index */
163 for (auto ziter
: zonegroup
->zones
) {
164 const string
& id
= ziter
.first
;
165 RGWZone
& z
= ziter
.second
;
166 zone_id_by_name
[z
.name
] = id
;
170 if (zone_by_id
.find(zone_id()) == zone_by_id
.end()) {
171 ldout(cct
, 0) << "WARNING: could not find zone config in zonegroup for local zone (" << zone_id() << "), will use defaults" << dendl
;
173 *zone_public_config
= zone_by_id
[zone_id()];
174 for (auto ziter
: zonegroup
->zones
) {
175 const string
& id
= ziter
.first
;
176 RGWZone
& z
= ziter
.second
;
177 if (id
== zone_id()) {
180 if (z
.endpoints
.empty()) {
181 ldout(cct
, 0) << "WARNING: can't generate connection for zone " << z
.id
<< " id " << z
.name
<< ": no endpoints defined" << dendl
;
184 ldout(cct
, 20) << "generating connection object for zone " << z
.name
<< " id " << z
.id
<< dendl
;
185 RGWRESTConn
*conn
= new RGWRESTConn(cct
, this, z
.id
, z
.endpoints
);
186 zone_conn_map
[id
] = conn
;
187 if (zone_syncs_from(*zone_public_config
, z
) ||
188 zone_syncs_from(z
, *zone_public_config
)) {
189 if (zone_syncs_from(*zone_public_config
, z
)) {
190 zone_data_sync_from_map
[id
] = conn
;
192 if (zone_syncs_from(z
, *zone_public_config
)) {
193 zone_data_notify_to_map
[id
] = conn
;
196 ldout(cct
, 20) << "NOTICE: not syncing to/from zone " << z
.name
<< " id " << z
.id
<< dendl
;
203 void RGWSI_Zone::shutdown()
205 delete rest_master_conn
;
207 map
<string
, RGWRESTConn
*>::iterator iter
;
208 for (iter
= zone_conn_map
.begin(); iter
!= zone_conn_map
.end(); ++iter
) {
209 RGWRESTConn
*conn
= iter
->second
;
213 for (iter
= zonegroup_conn_map
.begin(); iter
!= zonegroup_conn_map
.end(); ++iter
) {
214 RGWRESTConn
*conn
= iter
->second
;
219 int RGWSI_Zone::list_regions(list
<string
>& regions
)
221 RGWZoneGroup zonegroup
;
222 RGWSI_SysObj::Pool syspool
= sysobj_svc
->get_pool(zonegroup
.get_pool(cct
));
224 return syspool
.op().list_prefixed_objs(region_info_oid_prefix
, ®ions
);
227 int RGWSI_Zone::list_zonegroups(list
<string
>& zonegroups
)
229 RGWZoneGroup zonegroup
;
230 RGWSI_SysObj::Pool syspool
= sysobj_svc
->get_pool(zonegroup
.get_pool(cct
));
232 return syspool
.op().list_prefixed_objs(zonegroup_names_oid_prefix
, &zonegroups
);
235 int RGWSI_Zone::list_zones(list
<string
>& zones
)
237 RGWZoneParams zoneparams
;
238 RGWSI_SysObj::Pool syspool
= sysobj_svc
->get_pool(zoneparams
.get_pool(cct
));
240 return syspool
.op().list_prefixed_objs(zone_names_oid_prefix
, &zones
);
243 int RGWSI_Zone::list_realms(list
<string
>& realms
)
245 RGWRealm
realm(cct
, sysobj_svc
);
246 RGWSI_SysObj::Pool syspool
= sysobj_svc
->get_pool(realm
.get_pool(cct
));
248 return syspool
.op().list_prefixed_objs(realm_names_oid_prefix
, &realms
);
251 int RGWSI_Zone::list_periods(list
<string
>& periods
)
254 list
<string
> raw_periods
;
255 RGWSI_SysObj::Pool syspool
= sysobj_svc
->get_pool(period
.get_pool(cct
));
256 int ret
= syspool
.op().list_prefixed_objs(period
.get_info_oid_prefix(), &raw_periods
);
260 for (const auto& oid
: raw_periods
) {
261 size_t pos
= oid
.find(".");
262 if (pos
!= std::string::npos
) {
263 periods
.push_back(oid
.substr(0, pos
));
265 periods
.push_back(oid
);
268 periods
.sort(); // unique() only detects duplicates if they're adjacent
274 int RGWSI_Zone::list_periods(const string
& current_period
, list
<string
>& periods
)
277 string period_id
= current_period
;
278 while(!period_id
.empty()) {
279 RGWPeriod
period(period_id
);
280 ret
= period
.init(cct
, sysobj_svc
);
284 periods
.push_back(period
.get_id());
285 period_id
= period
.get_predecessor();
292 * Replace all region configuration with zonegroup for
293 * backward compatability
294 * Returns 0 on success, -ERR# on failure.
296 int RGWSI_Zone::replace_region_with_zonegroup()
298 /* copy default region */
299 /* convert default region to default zonegroup */
300 string default_oid
= cct
->_conf
->rgw_default_region_info_oid
;
301 if (default_oid
.empty()) {
302 default_oid
= default_region_info_oid
;
305 RGWZoneGroup default_zonegroup
;
306 rgw_pool pool
{default_zonegroup
.get_pool(cct
)};
307 string oid
= "converted";
310 RGWSysObjectCtx obj_ctx
= sysobj_svc
->init_obj_ctx();
311 RGWSysObj sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj(pool
, oid
));
313 int ret
= sysobj
.rop().read(&bl
);
314 if (ret
< 0 && ret
!= -ENOENT
) {
315 ldout(cct
, 0) << __func__
<< " failed to read converted: ret "<< ret
<< " " << cpp_strerror(-ret
)
318 } else if (ret
!= -ENOENT
) {
319 ldout(cct
, 20) << "System already converted " << dendl
;
323 string default_region
;
324 ret
= default_zonegroup
.init(cct
, sysobj_svc
, false, true);
326 ldout(cct
, 0) << __func__
<< " failed init default region: ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
329 ret
= default_zonegroup
.read_default_id(default_region
, true);
330 if (ret
< 0 && ret
!= -ENOENT
) {
331 ldout(cct
, 0) << __func__
<< " failed reading old default region: ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
335 /* convert regions to zonegroups */
336 list
<string
> regions
;
337 ret
= list_regions(regions
);
338 if (ret
< 0 && ret
!= -ENOENT
) {
339 ldout(cct
, 0) << __func__
<< " failed to list regions: ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
341 } else if (ret
== -ENOENT
|| regions
.empty()) {
342 RGWZoneParams
zoneparams(default_zone_name
);
343 int ret
= zoneparams
.init(cct
, sysobj_svc
);
344 if (ret
< 0 && ret
!= -ENOENT
) {
345 ldout(cct
, 0) << __func__
<< ": error initializing default zone params: " << cpp_strerror(-ret
) << dendl
;
348 /* update master zone */
349 RGWZoneGroup
default_zg(default_zonegroup_name
);
350 ret
= default_zg
.init(cct
, sysobj_svc
);
351 if (ret
< 0 && ret
!= -ENOENT
) {
352 ldout(cct
, 0) << __func__
<< ": error in initializing default zonegroup: " << cpp_strerror(-ret
) << dendl
;
355 if (ret
!= -ENOENT
&& default_zg
.master_zone
.empty()) {
356 default_zg
.master_zone
= zoneparams
.get_id();
357 return default_zg
.update();
362 string master_region
, master_zone
;
363 for (list
<string
>::iterator iter
= regions
.begin(); iter
!= regions
.end(); ++iter
) {
364 if (*iter
!= default_zonegroup_name
){
365 RGWZoneGroup
region(*iter
);
366 int ret
= region
.init(cct
, sysobj_svc
, true, true);
368 ldout(cct
, 0) << __func__
<< " failed init region "<< *iter
<< ": " << cpp_strerror(-ret
) << dendl
;
371 if (region
.is_master_zonegroup()) {
372 master_region
= region
.get_id();
373 master_zone
= region
.master_zone
;
378 /* create realm if there is none.
379 The realm name will be the region and zone concatenated
380 realm id will be mds of its name */
381 if (realm
->get_id().empty() && !master_region
.empty() && !master_zone
.empty()) {
382 string new_realm_name
= master_region
+ "." + master_zone
;
383 unsigned char md5
[CEPH_CRYPTO_MD5_DIGESTSIZE
];
384 char md5_str
[CEPH_CRYPTO_MD5_DIGESTSIZE
* 2 + 1];
386 hash
.Update((const unsigned char *)new_realm_name
.c_str(), new_realm_name
.length());
388 buf_to_hex(md5
, CEPH_CRYPTO_MD5_DIGESTSIZE
, md5_str
);
389 string
new_realm_id(md5_str
);
390 RGWRealm
new_realm(new_realm_id
,new_realm_name
);
391 ret
= new_realm
.init(cct
, sysobj_svc
, false);
393 ldout(cct
, 0) << __func__
<< " Error initing new realm: " << cpp_strerror(-ret
) << dendl
;
396 ret
= new_realm
.create();
397 if (ret
< 0 && ret
!= -EEXIST
) {
398 ldout(cct
, 0) << __func__
<< " Error creating new realm: " << cpp_strerror(-ret
) << dendl
;
401 ret
= new_realm
.set_as_default();
403 ldout(cct
, 0) << __func__
<< " Error setting realm as default: " << cpp_strerror(-ret
) << dendl
;
406 ret
= realm
->init(cct
, sysobj_svc
);
408 ldout(cct
, 0) << __func__
<< " Error initing realm: " << cpp_strerror(-ret
) << dendl
;
411 ret
= current_period
->init(cct
, sysobj_svc
, realm
->get_id(), realm
->get_name());
413 ldout(cct
, 0) << __func__
<< " Error initing current period: " << cpp_strerror(-ret
) << dendl
;
418 list
<string
>::iterator iter
;
419 /* create zonegroups */
420 for (iter
= regions
.begin(); iter
!= regions
.end(); ++iter
)
422 ldout(cct
, 0) << __func__
<< " Converting " << *iter
<< dendl
;
423 /* check to see if we don't have already a zonegroup with this name */
424 RGWZoneGroup
new_zonegroup(*iter
);
425 ret
= new_zonegroup
.init(cct
, sysobj_svc
);
426 if (ret
== 0 && new_zonegroup
.get_id() != *iter
) {
427 ldout(cct
, 0) << __func__
<< " zonegroup "<< *iter
<< " already exists id " << new_zonegroup
.get_id () <<
428 " skipping conversion " << dendl
;
431 RGWZoneGroup
zonegroup(*iter
);
432 zonegroup
.set_id(*iter
);
433 int ret
= zonegroup
.init(cct
, sysobj_svc
, true, true);
435 ldout(cct
, 0) << __func__
<< " failed init zonegroup: ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
438 zonegroup
.realm_id
= realm
->get_id();
439 /* fix default region master zone */
440 if (*iter
== default_zonegroup_name
&& zonegroup
.master_zone
.empty()) {
441 ldout(cct
, 0) << __func__
<< " Setting default zone as master for default region" << dendl
;
442 zonegroup
.master_zone
= default_zone_name
;
444 ret
= zonegroup
.update();
445 if (ret
< 0 && ret
!= -EEXIST
) {
446 ldout(cct
, 0) << __func__
<< " failed to update zonegroup " << *iter
<< ": ret "<< ret
<< " " << cpp_strerror(-ret
)
450 ret
= zonegroup
.update_name();
451 if (ret
< 0 && ret
!= -EEXIST
) {
452 ldout(cct
, 0) << __func__
<< " failed to update_name for zonegroup " << *iter
<< ": ret "<< ret
<< " " << cpp_strerror(-ret
)
456 if (zonegroup
.get_name() == default_region
) {
457 ret
= zonegroup
.set_as_default();
459 ldout(cct
, 0) << __func__
<< " failed to set_as_default " << *iter
<< ": ret "<< ret
<< " " << cpp_strerror(-ret
)
464 for (map
<string
, RGWZone
>::const_iterator iter
= zonegroup
.zones
.begin(); iter
!= zonegroup
.zones
.end();
466 ldout(cct
, 0) << __func__
<< " Converting zone" << iter
->first
<< dendl
;
467 RGWZoneParams
zoneparams(iter
->first
, iter
->first
);
468 zoneparams
.set_id(iter
->first
);
469 zoneparams
.realm_id
= realm
->get_id();
470 ret
= zoneparams
.init(cct
, sysobj_svc
);
471 if (ret
< 0 && ret
!= -ENOENT
) {
472 ldout(cct
, 0) << __func__
<< " failed to init zoneparams " << iter
->first
<< ": " << cpp_strerror(-ret
) << dendl
;
474 } else if (ret
== -ENOENT
) {
475 ldout(cct
, 0) << __func__
<< " zone is part of another cluster " << iter
->first
<< " skipping " << dendl
;
478 zonegroup
.realm_id
= realm
->get_id();
479 ret
= zoneparams
.update();
480 if (ret
< 0 && ret
!= -EEXIST
) {
481 ldout(cct
, 0) << __func__
<< " failed to update zoneparams " << iter
->first
<< ": " << cpp_strerror(-ret
) << dendl
;
484 ret
= zoneparams
.update_name();
485 if (ret
< 0 && ret
!= -EEXIST
) {
486 ldout(cct
, 0) << __func__
<< " failed to init zoneparams " << iter
->first
<< ": " << cpp_strerror(-ret
) << dendl
;
491 if (!current_period
->get_id().empty()) {
492 ret
= current_period
->add_zonegroup(zonegroup
);
494 ldout(cct
, 0) << __func__
<< " failed to add zonegroup to current_period: " << cpp_strerror(-ret
) << dendl
;
500 if (!current_period
->get_id().empty()) {
501 ret
= current_period
->update();
503 ldout(cct
, 0) << __func__
<< " failed to update new period: " << cpp_strerror(-ret
) << dendl
;
506 ret
= current_period
->store_info(false);
508 ldout(cct
, 0) << __func__
<< " failed to store new period: " << cpp_strerror(-ret
) << dendl
;
511 ret
= current_period
->reflect();
513 ldout(cct
, 0) << __func__
<< " failed to update local objects: " << cpp_strerror(-ret
) << dendl
;
518 for (auto const& iter
: regions
) {
519 RGWZoneGroup
zonegroup(iter
);
520 int ret
= zonegroup
.init(cct
, sysobj_svc
, true, true);
522 ldout(cct
, 0) << __func__
<< " failed init zonegroup" << iter
<< ": ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
525 ret
= zonegroup
.delete_obj(true);
526 if (ret
< 0 && ret
!= -ENOENT
) {
527 ldout(cct
, 0) << __func__
<< " failed to delete region " << iter
<< ": ret "<< ret
<< " " << cpp_strerror(-ret
)
533 /* mark as converted */
538 ldout(cct
, 0) << __func__
<< " failed to mark cluster as converted: ret "<< ret
<< " " << cpp_strerror(-ret
)
547 * Add new connection to connections map
548 * @param zonegroup_conn_map map which new connection will be added to
549 * @param zonegroup zonegroup which new connection will connect to
550 * @param new_connection pointer to new connection instance
552 static void add_new_connection_to_map(map
<string
, RGWRESTConn
*> &zonegroup_conn_map
,
553 const RGWZoneGroup
&zonegroup
, RGWRESTConn
*new_connection
)
555 // Delete if connection is already exists
556 map
<string
, RGWRESTConn
*>::iterator iterZoneGroup
= zonegroup_conn_map
.find(zonegroup
.get_id());
557 if (iterZoneGroup
!= zonegroup_conn_map
.end()) {
558 delete iterZoneGroup
->second
;
561 // Add new connection to connections map
562 zonegroup_conn_map
[zonegroup
.get_id()] = new_connection
;
565 int RGWSI_Zone::init_zg_from_period(bool *initialized
)
567 *initialized
= false;
569 if (current_period
->get_id().empty()) {
573 int ret
= zonegroup
->init(cct
, sysobj_svc
);
574 ldout(cct
, 20) << "period zonegroup init ret " << ret
<< dendl
;
575 if (ret
== -ENOENT
) {
579 ldout(cct
, 0) << "failed reading zonegroup info: " << cpp_strerror(-ret
) << dendl
;
582 ldout(cct
, 20) << "period zonegroup name " << zonegroup
->get_name() << dendl
;
584 map
<string
, RGWZoneGroup
>::const_iterator iter
=
585 current_period
->get_map().zonegroups
.find(zonegroup
->get_id());
587 if (iter
!= current_period
->get_map().zonegroups
.end()) {
588 ldout(cct
, 20) << "using current period zonegroup " << zonegroup
->get_name() << dendl
;
589 *zonegroup
= iter
->second
;
590 ret
= zonegroup
->init(cct
, sysobj_svc
, false);
592 ldout(cct
, 0) << "failed init zonegroup: " << " " << cpp_strerror(-ret
) << dendl
;
595 ret
= zone_params
->init(cct
, sysobj_svc
);
596 if (ret
< 0 && ret
!= -ENOENT
) {
597 ldout(cct
, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret
) << dendl
;
599 } if (ret
==-ENOENT
&& zonegroup
->get_name() == default_zonegroup_name
) {
600 ldout(cct
, 10) << " Using default name "<< default_zone_name
<< dendl
;
601 zone_params
->set_name(default_zone_name
);
602 ret
= zone_params
->init(cct
, sysobj_svc
);
603 if (ret
< 0 && ret
!= -ENOENT
) {
604 ldout(cct
, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret
) << dendl
;
609 for (iter
= current_period
->get_map().zonegroups
.begin();
610 iter
!= current_period
->get_map().zonegroups
.end(); ++iter
){
611 const RGWZoneGroup
& zg
= iter
->second
;
612 // use endpoints from the zonegroup's master zone
613 auto master
= zg
.zones
.find(zg
.master_zone
);
614 if (master
== zg
.zones
.end()) {
615 // Check for empty zonegroup which can happen if zone was deleted before removal
616 if (zg
.zones
.size() == 0)
618 // fix missing master zone for a single zone zonegroup
619 if (zg
.master_zone
.empty() && zg
.zones
.size() == 1) {
620 master
= zg
.zones
.begin();
621 ldout(cct
, 0) << "zonegroup " << zg
.get_name() << " missing master_zone, setting zone " <<
622 master
->second
.name
<< " id:" << master
->second
.id
<< " as master" << dendl
;
623 if (zonegroup
->get_id() == zg
.get_id()) {
624 zonegroup
->master_zone
= master
->second
.id
;
625 ret
= zonegroup
->update();
627 ldout(cct
, 0) << "error updating zonegroup : " << cpp_strerror(-ret
) << dendl
;
631 RGWZoneGroup
fixed_zg(zg
.get_id(),zg
.get_name());
632 ret
= fixed_zg
.init(cct
, sysobj_svc
);
634 ldout(cct
, 0) << "error initializing zonegroup : " << cpp_strerror(-ret
) << dendl
;
637 fixed_zg
.master_zone
= master
->second
.id
;
638 ret
= fixed_zg
.update();
640 ldout(cct
, 0) << "error initializing zonegroup : " << cpp_strerror(-ret
) << dendl
;
645 ldout(cct
, 0) << "zonegroup " << zg
.get_name() << " missing zone for master_zone=" <<
646 zg
.master_zone
<< dendl
;
650 const auto& endpoints
= master
->second
.endpoints
;
651 add_new_connection_to_map(zonegroup_conn_map
, zg
, new RGWRESTConn(cct
, this, zg
.get_id(), endpoints
));
652 if (!current_period
->get_master_zonegroup().empty() &&
653 zg
.get_id() == current_period
->get_master_zonegroup()) {
654 rest_master_conn
= new RGWRESTConn(cct
, this, zg
.get_id(), endpoints
);
663 int RGWSI_Zone::init_zg_from_local(bool *creating_defaults
)
665 int ret
= zonegroup
->init(cct
, sysobj_svc
);
666 if ( (ret
< 0 && ret
!= -ENOENT
) || (ret
== -ENOENT
&& !cct
->_conf
->rgw_zonegroup
.empty())) {
667 ldout(cct
, 0) << "failed reading zonegroup info: ret "<< ret
<< " " << cpp_strerror(-ret
) << dendl
;
669 } else if (ret
== -ENOENT
) {
670 *creating_defaults
= true;
671 ldout(cct
, 10) << "Creating default zonegroup " << dendl
;
672 ret
= zonegroup
->create_default();
674 ldout(cct
, 0) << "failure in zonegroup create_default: ret "<< ret
<< " " << cpp_strerror(-ret
)
678 ret
= zonegroup
->init(cct
, sysobj_svc
);
680 ldout(cct
, 0) << "failure in zonegroup create_default: ret "<< ret
<< " " << cpp_strerror(-ret
)
685 ldout(cct
, 20) << "zonegroup " << zonegroup
->get_name() << dendl
;
686 if (zonegroup
->is_master_zonegroup()) {
687 // use endpoints from the zonegroup's master zone
688 auto master
= zonegroup
->zones
.find(zonegroup
->master_zone
);
689 if (master
== zonegroup
->zones
.end()) {
690 // fix missing master zone for a single zone zonegroup
691 if (zonegroup
->master_zone
.empty() && zonegroup
->zones
.size() == 1) {
692 master
= zonegroup
->zones
.begin();
693 ldout(cct
, 0) << "zonegroup " << zonegroup
->get_name() << " missing master_zone, setting zone " <<
694 master
->second
.name
<< " id:" << master
->second
.id
<< " as master" << dendl
;
695 zonegroup
->master_zone
= master
->second
.id
;
696 ret
= zonegroup
->update();
698 ldout(cct
, 0) << "error initializing zonegroup : " << cpp_strerror(-ret
) << dendl
;
702 ldout(cct
, 0) << "zonegroup " << zonegroup
->get_name() << " missing zone for "
703 "master_zone=" << zonegroup
->master_zone
<< dendl
;
707 const auto& endpoints
= master
->second
.endpoints
;
708 rest_master_conn
= new RGWRESTConn(cct
, this, zonegroup
->get_id(), endpoints
);
714 int RGWSI_Zone::convert_regionmap()
716 RGWZoneGroupMap zonegroupmap
;
718 string pool_name
= cct
->_conf
->rgw_zone_root_pool
;
719 if (pool_name
.empty()) {
720 pool_name
= RGW_DEFAULT_ZONE_ROOT_POOL
;
722 string oid
= region_map_oid
;
724 rgw_pool
pool(pool_name
);
727 RGWSysObjectCtx obj_ctx
= sysobj_svc
->init_obj_ctx();
728 RGWSysObj sysobj
= sysobj_svc
->get_obj(obj_ctx
, rgw_raw_obj(pool
, oid
));
730 int ret
= sysobj
.rop().read(&bl
);
731 if (ret
< 0 && ret
!= -ENOENT
) {
733 } else if (ret
== -ENOENT
) {
738 auto iter
= bl
.cbegin();
739 decode(zonegroupmap
, iter
);
740 } catch (buffer::error
& err
) {
741 ldout(cct
, 0) << "error decoding regionmap from " << pool
<< ":" << oid
<< dendl
;
745 for (map
<string
, RGWZoneGroup
>::iterator iter
= zonegroupmap
.zonegroups
.begin();
746 iter
!= zonegroupmap
.zonegroups
.end(); ++iter
) {
747 RGWZoneGroup
& zonegroup
= iter
->second
;
748 ret
= zonegroup
.init(cct
, sysobj_svc
, false);
749 ret
= zonegroup
.update();
750 if (ret
< 0 && ret
!= -ENOENT
) {
751 ldout(cct
, 0) << "Error could not update zonegroup " << zonegroup
.get_name() << ": " <<
752 cpp_strerror(-ret
) << dendl
;
754 } else if (ret
== -ENOENT
) {
755 ret
= zonegroup
.create();
757 ldout(cct
, 0) << "Error could not create " << zonegroup
.get_name() << ": " <<
758 cpp_strerror(-ret
) << dendl
;
764 current_period
->set_user_quota(zonegroupmap
.user_quota
);
765 current_period
->set_bucket_quota(zonegroupmap
.bucket_quota
);
767 // remove the region_map so we don't try to convert again
768 ret
= sysobj
.wop().remove();
770 ldout(cct
, 0) << "Error could not remove " << sysobj
.get_obj()
771 << " after upgrading to zonegroup map: " << cpp_strerror(ret
) << dendl
;
778 const RGWZoneParams
& RGWSI_Zone::get_zone_params() const
783 const RGWZone
& RGWSI_Zone::get_zone() const
785 return *zone_public_config
;
788 const RGWZoneGroup
& RGWSI_Zone::get_zonegroup() const
793 int RGWSI_Zone::get_zonegroup(const string
& id
, RGWZoneGroup
& zg
) const
796 if (id
== zonegroup
->get_id()) {
798 } else if (!current_period
->get_id().empty()) {
799 ret
= current_period
->get_zonegroup(zg
, id
);
804 const RGWRealm
& RGWSI_Zone::get_realm() const
809 const RGWPeriod
& RGWSI_Zone::get_current_period() const
811 return *current_period
;
814 const string
& RGWSI_Zone::get_current_period_id()
816 return current_period
->get_id();
819 bool RGWSI_Zone::has_zonegroup_api(const std::string
& api
) const
821 if (!current_period
->get_id().empty()) {
822 const auto& zonegroups_by_api
= current_period
->get_map().zonegroups_by_api
;
823 if (zonegroups_by_api
.find(api
) != zonegroups_by_api
.end())
825 } else if (zonegroup
->api_name
== api
) {
831 bool RGWSI_Zone::zone_is_writeable()
833 return writeable_zone
&& !get_zone().is_read_only();
836 uint32_t RGWSI_Zone::get_zone_short_id() const
838 return zone_short_id
;
841 const string
& RGWSI_Zone::zone_name()
843 return get_zone_params().get_name();
845 const string
& RGWSI_Zone::zone_id()
847 return get_zone_params().get_id();
850 bool RGWSI_Zone::find_zone_by_id(const string
& id
, RGWZone
**zone
)
852 auto iter
= zone_by_id
.find(id
);
853 if (iter
== zone_by_id
.end()) {
856 *zone
= &(iter
->second
);
860 RGWRESTConn
*RGWSI_Zone::get_zone_conn_by_id(const string
& id
) {
861 auto citer
= zone_conn_map
.find(id
);
862 if (citer
== zone_conn_map
.end()) {
866 return citer
->second
;
869 RGWRESTConn
*RGWSI_Zone::get_zone_conn_by_name(const string
& name
) {
870 auto i
= zone_id_by_name
.find(name
);
871 if (i
== zone_id_by_name
.end()) {
875 return get_zone_conn_by_id(i
->second
);
878 bool RGWSI_Zone::find_zone_id_by_name(const string
& name
, string
*id
) {
879 auto i
= zone_id_by_name
.find(name
);
880 if (i
== zone_id_by_name
.end()) {
887 bool RGWSI_Zone::need_to_log_data() const
889 return zone_public_config
->log_data
;
892 bool RGWSI_Zone::is_meta_master() const
894 if (!zonegroup
->is_master_zonegroup()) {
898 return (zonegroup
->master_zone
== zone_public_config
->id
);
901 bool RGWSI_Zone::need_to_log_metadata() const
903 return is_meta_master() &&
904 (zonegroup
->zones
.size() > 1 || current_period
->is_multi_zonegroups_with_zones());
907 bool RGWSI_Zone::can_reshard() const
909 return current_period
->get_id().empty() ||
910 (zonegroup
->zones
.size() == 1 && current_period
->is_single_zonegroup());
914 * Check to see if the bucket metadata could be synced
915 * bucket: the bucket to check
916 * Returns false is the bucket is not synced
918 bool RGWSI_Zone::is_syncing_bucket_meta(const rgw_bucket
& bucket
)
921 /* no current period */
922 if (current_period
->get_id().empty()) {
926 /* zonegroup is not master zonegroup */
927 if (!zonegroup
->is_master_zonegroup()) {
931 /* single zonegroup and a single zone */
932 if (current_period
->is_single_zonegroup() && zonegroup
->zones
.size() == 1) {
936 /* zone is not master */
937 if (zonegroup
->master_zone
.compare(zone_public_config
->id
) != 0) {
945 int RGWSI_Zone::select_new_bucket_location(const RGWUserInfo
& user_info
, const string
& zonegroup_id
,
946 const rgw_placement_rule
& request_rule
,
947 rgw_placement_rule
*pselected_rule_name
, RGWZonePlacementInfo
*rule_info
)
949 /* first check that zonegroup exists within current period. */
950 RGWZoneGroup zonegroup
;
951 int ret
= get_zonegroup(zonegroup_id
, zonegroup
);
953 ldout(cct
, 0) << "could not find zonegroup " << zonegroup_id
<< " in current period" << dendl
;
957 const rgw_placement_rule
*used_rule
;
959 /* find placement rule. Hierarchy: request rule > user default rule > zonegroup default rule */
960 std::map
<std::string
, RGWZoneGroupPlacementTarget
>::const_iterator titer
;
962 if (!request_rule
.name
.empty()) {
963 used_rule
= &request_rule
;
964 titer
= zonegroup
.placement_targets
.find(request_rule
.name
);
965 if (titer
== zonegroup
.placement_targets
.end()) {
966 ldout(cct
, 0) << "could not find requested placement id " << request_rule
967 << " within zonegroup " << dendl
;
968 return -ERR_INVALID_LOCATION_CONSTRAINT
;
970 } else if (!user_info
.default_placement
.name
.empty()) {
971 used_rule
= &user_info
.default_placement
;
972 titer
= zonegroup
.placement_targets
.find(user_info
.default_placement
.name
);
973 if (titer
== zonegroup
.placement_targets
.end()) {
974 ldout(cct
, 0) << "could not find user default placement id " << user_info
.default_placement
975 << " within zonegroup " << dendl
;
976 return -ERR_INVALID_LOCATION_CONSTRAINT
;
979 if (zonegroup
.default_placement
.name
.empty()) { // zonegroup default rule as fallback, it should not be empty.
980 ldout(cct
, 0) << "misconfiguration, zonegroup default placement id should not be empty." << dendl
;
981 return -ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION
;
983 used_rule
= &zonegroup
.default_placement
;
984 titer
= zonegroup
.placement_targets
.find(zonegroup
.default_placement
.name
);
985 if (titer
== zonegroup
.placement_targets
.end()) {
986 ldout(cct
, 0) << "could not find zonegroup default placement id " << zonegroup
.default_placement
987 << " within zonegroup " << dendl
;
988 return -ERR_INVALID_LOCATION_CONSTRAINT
;
993 /* now check tag for the rule, whether user is permitted to use rule */
994 const auto& target_rule
= titer
->second
;
995 if (!target_rule
.user_permitted(user_info
.placement_tags
)) {
996 ldout(cct
, 0) << "user not permitted to use placement rule " << titer
->first
<< dendl
;
1000 const string
*storage_class
= &request_rule
.storage_class
;
1002 if (storage_class
->empty()) {
1003 storage_class
= &used_rule
->storage_class
;
1006 rgw_placement_rule
rule(titer
->first
, *storage_class
);
1008 if (pselected_rule_name
) {
1009 *pselected_rule_name
= rule
;
1012 return select_bucket_location_by_rule(rule
, rule_info
);
1015 int RGWSI_Zone::select_bucket_location_by_rule(const rgw_placement_rule
& location_rule
, RGWZonePlacementInfo
*rule_info
)
1017 if (location_rule
.name
.empty()) {
1018 /* we can only reach here if we're trying to set a bucket location from a bucket
1019 * created on a different zone, using a legacy / default pool configuration
1022 return select_legacy_bucket_placement(rule_info
);
1029 * make sure that zone has this rule configured. We're
1030 * checking it for the local zone, because that's where this bucket object is going to
1033 auto piter
= zone_params
->placement_pools
.find(location_rule
.name
);
1034 if (piter
== zone_params
->placement_pools
.end()) {
1035 /* couldn't find, means we cannot really place data for this bucket in this zone */
1036 ldout(cct
, 0) << "ERROR: This zone does not contain placement rule "
1037 << location_rule
<< " present in the zonegroup!" << dendl
;
1041 auto storage_class
= location_rule
.get_storage_class();
1042 if (!piter
->second
.storage_class_exists(storage_class
)) {
1043 ldout(cct
, 5) << "requested storage class does not exist: " << storage_class
<< dendl
;
1048 RGWZonePlacementInfo
& placement_info
= piter
->second
;
1051 *rule_info
= placement_info
;
1057 int RGWSI_Zone::select_bucket_placement(const RGWUserInfo
& user_info
, const string
& zonegroup_id
,
1058 const rgw_placement_rule
& placement_rule
,
1059 rgw_placement_rule
*pselected_rule
, RGWZonePlacementInfo
*rule_info
)
1061 if (!zone_params
->placement_pools
.empty()) {
1062 return select_new_bucket_location(user_info
, zonegroup_id
, placement_rule
,
1063 pselected_rule
, rule_info
);
1066 if (pselected_rule
) {
1067 pselected_rule
->clear();
1071 return select_legacy_bucket_placement(rule_info
);
1077 int RGWSI_Zone::select_legacy_bucket_placement(RGWZonePlacementInfo
*rule_info
)
1080 map
<string
, bufferlist
> m
;
1082 bool write_map
= false;
1084 rgw_raw_obj
obj(zone_params
->domain_root
, avail_pools
);
1086 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1087 auto sysobj
= obj_ctx
.get_obj(obj
);
1089 int ret
= sysobj
.rop().read(&map_bl
);
1095 auto iter
= map_bl
.cbegin();
1097 } catch (buffer::error
& err
) {
1098 ldout(cct
, 0) << "ERROR: couldn't decode avail_pools" << dendl
;
1103 ret
= sysobj
.omap().get_all(&m
);
1108 if (ret
< 0 || m
.empty()) {
1109 vector
<rgw_pool
> pools
;
1110 string s
= string("default.") + default_storage_pool_suffix
;
1111 pools
.push_back(rgw_pool(s
));
1112 vector
<int> retcodes
;
1114 ret
= rados_svc
->pool().create(pools
, &retcodes
);
1117 ret
= sysobj
.omap().set(s
, bl
);
1126 ret
= sysobj
.wop().write(new_bl
);
1128 ldout(cct
, 0) << "WARNING: could not save avail pools map info ret=" << ret
<< dendl
;
1132 auto miter
= m
.begin();
1134 // choose a pool at random
1135 auto r
= ceph::util::generate_random_number
<size_t>(0, m
.size() - 1);
1136 std::advance(miter
, r
);
1138 pool_name
= miter
->first
;
1140 rgw_pool pool
= pool_name
;
1142 rule_info
->storage_classes
.set_storage_class(RGW_STORAGE_CLASS_STANDARD
, &pool
, nullptr);
1143 rule_info
->data_extra_pool
= pool_name
;
1144 rule_info
->index_pool
= pool_name
;
1145 rule_info
->index_type
= RGWBIType_Normal
;
1150 int RGWSI_Zone::update_placement_map()
1153 map
<string
, bufferlist
> m
;
1154 rgw_raw_obj
obj(zone_params
->domain_root
, avail_pools
);
1156 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1157 auto sysobj
= obj_ctx
.get_obj(obj
);
1159 int ret
= sysobj
.omap().get_all(&m
);
1165 ret
= sysobj
.wop().write(new_bl
);
1167 ldout(cct
, 0) << "WARNING: could not save avail pools map info ret=" << ret
<< dendl
;
1173 int RGWSI_Zone::add_bucket_placement(const rgw_pool
& new_pool
)
1175 int ret
= rados_svc
->pool(new_pool
).lookup();
1176 if (ret
< 0) { // DNE, or something
1180 rgw_raw_obj
obj(zone_params
->domain_root
, avail_pools
);
1181 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1182 auto sysobj
= obj_ctx
.get_obj(obj
);
1184 bufferlist empty_bl
;
1185 ret
= sysobj
.omap().set(new_pool
.to_str(), empty_bl
);
1187 // don't care about return value
1188 update_placement_map();
1193 int RGWSI_Zone::remove_bucket_placement(const rgw_pool
& old_pool
)
1195 rgw_raw_obj
obj(zone_params
->domain_root
, avail_pools
);
1196 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1197 auto sysobj
= obj_ctx
.get_obj(obj
);
1199 int ret
= sysobj
.omap().del(old_pool
.to_str());
1201 // don't care about return value
1202 update_placement_map();
1207 int RGWSI_Zone::list_placement_set(set
<rgw_pool
>& names
)
1210 map
<string
, bufferlist
> m
;
1212 rgw_raw_obj
obj(zone_params
->domain_root
, avail_pools
);
1213 auto obj_ctx
= sysobj_svc
->init_obj_ctx();
1214 auto sysobj
= obj_ctx
.get_obj(obj
);
1215 int ret
= sysobj
.omap().get_all(&m
);
1220 map
<string
, bufferlist
>::iterator miter
;
1221 for (miter
= m
.begin(); miter
!= m
.end(); ++miter
) {
1222 names
.insert(rgw_pool(miter
->first
));
1225 return names
.size();
1228 bool RGWSI_Zone::get_redirect_zone_endpoint(string
*endpoint
)
1230 if (zone_public_config
->redirect_zone
.empty()) {
1234 auto iter
= zone_conn_map
.find(zone_public_config
->redirect_zone
);
1235 if (iter
== zone_conn_map
.end()) {
1236 ldout(cct
, 0) << "ERROR: cannot find entry for redirect zone: " << zone_public_config
->redirect_zone
<< dendl
;
1240 RGWRESTConn
*conn
= iter
->second
;
1242 int ret
= conn
->get_url(*endpoint
);
1244 ldout(cct
, 0) << "ERROR: redirect zone, conn->get_endpoint() returned ret=" << ret
<< dendl
;