]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/services/svc_zone.cc
import 15.2.0 Octopus source
[ceph.git] / ceph / src / rgw / services / svc_zone.cc
CommitLineData
9f95a23c
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab ft=cpp
3
11fdf7f2
TL
4#include "svc_zone.h"
5#include "svc_rados.h"
6#include "svc_sys_obj.h"
7#include "svc_sync_modules.h"
8
9#include "rgw/rgw_zone.h"
10#include "rgw/rgw_rest_conn.h"
9f95a23c 11#include "rgw/rgw_bucket_sync.h"
11fdf7f2
TL
12
13#include "common/errno.h"
14#include "include/random.h"
15
16#define dout_subsys ceph_subsys_rgw
17
18using namespace rgw_zone_defaults;
19
20RGWSI_Zone::RGWSI_Zone(CephContext *cct) : RGWServiceInstance(cct)
21{
22}
23
24void RGWSI_Zone::init(RGWSI_SysObj *_sysobj_svc,
25 RGWSI_RADOS * _rados_svc,
9f95a23c
TL
26 RGWSI_SyncModules * _sync_modules_svc,
27 RGWSI_Bucket_Sync *_bucket_sync_svc)
11fdf7f2
TL
28{
29 sysobj_svc = _sysobj_svc;
30 rados_svc = _rados_svc;
31 sync_modules_svc = _sync_modules_svc;
9f95a23c 32 bucket_sync_svc = _bucket_sync_svc;
11fdf7f2
TL
33
34 realm = new RGWRealm();
35 zonegroup = new RGWZoneGroup();
36 zone_public_config = new RGWZone();
37 zone_params = new RGWZoneParams();
38 current_period = new RGWPeriod();
39}
40
41RGWSI_Zone::~RGWSI_Zone()
42{
43 delete realm;
44 delete zonegroup;
45 delete zone_public_config;
46 delete zone_params;
47 delete current_period;
48}
49
9f95a23c
TL
50std::shared_ptr<RGWBucketSyncPolicyHandler> RGWSI_Zone::get_sync_policy_handler(std::optional<rgw_zone_id> zone) const {
51 if (!zone || *zone == zone_id()) {
52 return sync_policy_handler;
53 }
54 auto iter = sync_policy_handlers.find(*zone);
55 if (iter == sync_policy_handlers.end()) {
56 return std::shared_ptr<RGWBucketSyncPolicyHandler>();
57 }
58 return iter->second;
59}
60
11fdf7f2
TL
61bool RGWSI_Zone::zone_syncs_from(const RGWZone& target_zone, const RGWZone& source_zone) const
62{
63 return target_zone.syncs_from(source_zone.name) &&
64 sync_modules_svc->get_manager()->supports_data_export(source_zone.tier_type);
65}
66
67int RGWSI_Zone::do_start()
68{
69 int ret = sysobj_svc->start();
70 if (ret < 0) {
71 return ret;
72 }
73
74 assert(sysobj_svc->is_started()); /* if not then there's ordering issue */
75
76 ret = rados_svc->start();
77 if (ret < 0) {
78 return ret;
79 }
9f95a23c 80
11fdf7f2
TL
81 ret = realm->init(cct, sysobj_svc);
82 if (ret < 0 && ret != -ENOENT) {
83 ldout(cct, 0) << "failed reading realm info: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
84 return ret;
85 } else if (ret != -ENOENT) {
86 ldout(cct, 20) << "realm " << realm->get_name() << " " << realm->get_id() << dendl;
87 ret = current_period->init(cct, sysobj_svc, realm->get_id(), realm->get_name());
88 if (ret < 0 && ret != -ENOENT) {
89 ldout(cct, 0) << "failed reading current period info: " << " " << cpp_strerror(-ret) << dendl;
90 return ret;
91 }
92 ldout(cct, 20) << "current period " << current_period->get_id() << dendl;
93 }
94
95 ret = replace_region_with_zonegroup();
96 if (ret < 0) {
97 lderr(cct) << "failed converting region to zonegroup : ret "<< ret << " " << cpp_strerror(-ret) << dendl;
98 return ret;
99 }
100
101 ret = convert_regionmap();
102 if (ret < 0) {
103 lderr(cct) << "failed converting regionmap: " << cpp_strerror(-ret) << dendl;
104 return ret;
105 }
106
107 bool zg_initialized = false;
108
109 if (!current_period->get_id().empty()) {
110 ret = init_zg_from_period(&zg_initialized);
111 if (ret < 0) {
112 return ret;
113 }
114 }
115
116 bool creating_defaults = false;
117 bool using_local = (!zg_initialized);
118 if (using_local) {
119 ldout(cct, 10) << " cannot find current period zonegroup using local zonegroup" << dendl;
120 ret = init_zg_from_local(&creating_defaults);
121 if (ret < 0) {
122 return ret;
123 }
124 // read period_config into current_period
125 auto& period_config = current_period->get_config();
126 ret = period_config.read(sysobj_svc, zonegroup->realm_id);
127 if (ret < 0 && ret != -ENOENT) {
128 ldout(cct, 0) << "ERROR: failed to read period config: "
129 << cpp_strerror(ret) << dendl;
130 return ret;
131 }
132 }
133
134 ldout(cct, 10) << "Cannot find current period zone using local zone" << dendl;
135 if (creating_defaults && cct->_conf->rgw_zone.empty()) {
136 ldout(cct, 10) << " Using default name "<< default_zone_name << dendl;
137 zone_params->set_name(default_zone_name);
138 }
139
140 ret = zone_params->init(cct, sysobj_svc);
141 if (ret < 0 && ret != -ENOENT) {
142 lderr(cct) << "failed reading zone info: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
143 return ret;
144 }
9f95a23c
TL
145
146 cur_zone_id = rgw_zone_id(zone_params->get_id());
147
11fdf7f2
TL
148 auto zone_iter = zonegroup->zones.find(zone_params->get_id());
149 if (zone_iter == zonegroup->zones.end()) {
150 if (using_local) {
151 lderr(cct) << "Cannot find zone id=" << zone_params->get_id() << " (name=" << zone_params->get_name() << ")" << dendl;
152 return -EINVAL;
153 }
154 ldout(cct, 1) << "Cannot find zone id=" << zone_params->get_id() << " (name=" << zone_params->get_name() << "), switching to local zonegroup configuration" << dendl;
155 ret = init_zg_from_local(&creating_defaults);
156 if (ret < 0) {
157 return ret;
158 }
159 zone_iter = zonegroup->zones.find(zone_params->get_id());
160 }
161 if (zone_iter != zonegroup->zones.end()) {
162 *zone_public_config = zone_iter->second;
9f95a23c 163 ldout(cct, 20) << "zone " << zone_params->get_name() << " found" << dendl;
11fdf7f2
TL
164 } else {
165 lderr(cct) << "Cannot find zone id=" << zone_params->get_id() << " (name=" << zone_params->get_name() << ")" << dendl;
166 return -EINVAL;
167 }
168
169 zone_short_id = current_period->get_map().get_zone_short_id(zone_params->get_id());
170
9f95a23c
TL
171 for (auto ziter : zonegroup->zones) {
172 auto zone_handler = std::make_shared<RGWBucketSyncPolicyHandler>(this, sync_modules_svc, bucket_sync_svc, ziter.second.id);
173 ret = zone_handler->init(null_yield);
174 if (ret < 0) {
175 lderr(cct) << "ERROR: could not initialize zone policy handler for zone=" << ziter.second.name << dendl;
176 return ret;
177 }
178 sync_policy_handlers[ziter.second.id] = zone_handler;
179 }
180
181 sync_policy_handler = sync_policy_handlers[zone_id()]; /* we made sure earlier that zonegroup->zones has our zone */
182
183 set<rgw_zone_id> source_zones;
184 set<rgw_zone_id> target_zones;
185
186 sync_policy_handler->reflect(nullptr, nullptr,
187 nullptr, nullptr,
188 &source_zones,
189 &target_zones,
190 false); /* relaxed: also get all zones that we allow to sync to/from */
191
192 ret = sync_modules_svc->start();
193 if (ret < 0) {
194 return ret;
195 }
196
197 auto sync_modules = sync_modules_svc->get_manager();
11fdf7f2 198 RGWSyncModuleRef sm;
9f95a23c 199 if (!sync_modules->get_module(zone_public_config->tier_type, &sm)) {
11fdf7f2
TL
200 lderr(cct) << "ERROR: tier type not found: " << zone_public_config->tier_type << dendl;
201 return -EINVAL;
202 }
203
204 writeable_zone = sm->supports_writes();
9f95a23c 205 exports_data = sm->supports_data_export();
11fdf7f2
TL
206
207 /* first build all zones index */
208 for (auto ziter : zonegroup->zones) {
9f95a23c 209 const rgw_zone_id& id = ziter.first;
11fdf7f2
TL
210 RGWZone& z = ziter.second;
211 zone_id_by_name[z.name] = id;
212 zone_by_id[id] = z;
213 }
214
215 if (zone_by_id.find(zone_id()) == zone_by_id.end()) {
216 ldout(cct, 0) << "WARNING: could not find zone config in zonegroup for local zone (" << zone_id() << "), will use defaults" << dendl;
217 }
9f95a23c 218
81eedcae 219 for (const auto& ziter : zonegroup->zones) {
9f95a23c 220 const rgw_zone_id& id = ziter.first;
81eedcae 221 const RGWZone& z = ziter.second;
11fdf7f2
TL
222 if (id == zone_id()) {
223 continue;
224 }
225 if (z.endpoints.empty()) {
226 ldout(cct, 0) << "WARNING: can't generate connection for zone " << z.id << " id " << z.name << ": no endpoints defined" << dendl;
227 continue;
228 }
229 ldout(cct, 20) << "generating connection object for zone " << z.name << " id " << z.id << dendl;
230 RGWRESTConn *conn = new RGWRESTConn(cct, this, z.id, z.endpoints);
231 zone_conn_map[id] = conn;
9f95a23c
TL
232
233 bool zone_is_source = source_zones.find(z.id) != source_zones.end();
234 bool zone_is_target = target_zones.find(z.id) != target_zones.end();
235
236 if (zone_is_source || zone_is_target) {
237 if (zone_is_source && sync_modules->supports_data_export(z.tier_type)) {
81eedcae 238 data_sync_source_zones.push_back(&z);
11fdf7f2 239 }
9f95a23c 240 if (zone_is_target) {
11fdf7f2
TL
241 zone_data_notify_to_map[id] = conn;
242 }
243 } else {
244 ldout(cct, 20) << "NOTICE: not syncing to/from zone " << z.name << " id " << z.id << dendl;
245 }
246 }
247
9f95a23c
TL
248 ldout(cct, 20) << "started zone id=" << zone_params->get_id() << " (name=" << zone_params->get_name() <<
249 ") with tier type = " << zone_public_config->tier_type << dendl;
250
11fdf7f2
TL
251 return 0;
252}
253
254void RGWSI_Zone::shutdown()
255{
256 delete rest_master_conn;
257
9f95a23c
TL
258 for (auto& item : zone_conn_map) {
259 auto conn = item.second;
11fdf7f2
TL
260 delete conn;
261 }
262
9f95a23c
TL
263 for (auto& item : zonegroup_conn_map) {
264 auto conn = item.second;
11fdf7f2
TL
265 delete conn;
266 }
267}
268
269int RGWSI_Zone::list_regions(list<string>& regions)
270{
271 RGWZoneGroup zonegroup;
272 RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(zonegroup.get_pool(cct));
273
9f95a23c 274 return syspool.list_prefixed_objs(region_info_oid_prefix, &regions);
11fdf7f2
TL
275}
276
277int RGWSI_Zone::list_zonegroups(list<string>& zonegroups)
278{
279 RGWZoneGroup zonegroup;
280 RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(zonegroup.get_pool(cct));
281
9f95a23c 282 return syspool.list_prefixed_objs(zonegroup_names_oid_prefix, &zonegroups);
11fdf7f2
TL
283}
284
285int RGWSI_Zone::list_zones(list<string>& zones)
286{
287 RGWZoneParams zoneparams;
288 RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(zoneparams.get_pool(cct));
289
9f95a23c 290 return syspool.list_prefixed_objs(zone_names_oid_prefix, &zones);
11fdf7f2
TL
291}
292
293int RGWSI_Zone::list_realms(list<string>& realms)
294{
295 RGWRealm realm(cct, sysobj_svc);
296 RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(realm.get_pool(cct));
297
9f95a23c 298 return syspool.list_prefixed_objs(realm_names_oid_prefix, &realms);
11fdf7f2
TL
299}
300
301int RGWSI_Zone::list_periods(list<string>& periods)
302{
303 RGWPeriod period;
304 list<string> raw_periods;
305 RGWSI_SysObj::Pool syspool = sysobj_svc->get_pool(period.get_pool(cct));
9f95a23c 306 int ret = syspool.list_prefixed_objs(period.get_info_oid_prefix(), &raw_periods);
11fdf7f2
TL
307 if (ret < 0) {
308 return ret;
309 }
310 for (const auto& oid : raw_periods) {
311 size_t pos = oid.find(".");
312 if (pos != std::string::npos) {
313 periods.push_back(oid.substr(0, pos));
314 } else {
315 periods.push_back(oid);
316 }
317 }
318 periods.sort(); // unique() only detects duplicates if they're adjacent
319 periods.unique();
320 return 0;
321}
322
323
324int RGWSI_Zone::list_periods(const string& current_period, list<string>& periods)
325{
326 int ret = 0;
327 string period_id = current_period;
328 while(!period_id.empty()) {
329 RGWPeriod period(period_id);
330 ret = period.init(cct, sysobj_svc);
331 if (ret < 0) {
332 return ret;
333 }
334 periods.push_back(period.get_id());
335 period_id = period.get_predecessor();
336 }
337
338 return ret;
339}
340
341/**
342 * Replace all region configuration with zonegroup for
343 * backward compatability
344 * Returns 0 on success, -ERR# on failure.
345 */
346int RGWSI_Zone::replace_region_with_zonegroup()
347{
348 /* copy default region */
349 /* convert default region to default zonegroup */
350 string default_oid = cct->_conf->rgw_default_region_info_oid;
351 if (default_oid.empty()) {
352 default_oid = default_region_info_oid;
353 }
354
355 RGWZoneGroup default_zonegroup;
356 rgw_pool pool{default_zonegroup.get_pool(cct)};
357 string oid = "converted";
358 bufferlist bl;
359
360 RGWSysObjectCtx obj_ctx = sysobj_svc->init_obj_ctx();
361 RGWSysObj sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
362
9f95a23c 363 int ret = sysobj.rop().read(&bl, null_yield);
11fdf7f2
TL
364 if (ret < 0 && ret != -ENOENT) {
365 ldout(cct, 0) << __func__ << " failed to read converted: ret "<< ret << " " << cpp_strerror(-ret)
366 << dendl;
367 return ret;
368 } else if (ret != -ENOENT) {
369 ldout(cct, 20) << "System already converted " << dendl;
370 return 0;
371 }
372
373 string default_region;
374 ret = default_zonegroup.init(cct, sysobj_svc, false, true);
375 if (ret < 0) {
376 ldout(cct, 0) << __func__ << " failed init default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
377 return ret;
378 }
379 ret = default_zonegroup.read_default_id(default_region, true);
380 if (ret < 0 && ret != -ENOENT) {
381 ldout(cct, 0) << __func__ << " failed reading old default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
382 return ret;
383 }
384
385 /* convert regions to zonegroups */
386 list<string> regions;
387 ret = list_regions(regions);
388 if (ret < 0 && ret != -ENOENT) {
389 ldout(cct, 0) << __func__ << " failed to list regions: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
390 return ret;
391 } else if (ret == -ENOENT || regions.empty()) {
392 RGWZoneParams zoneparams(default_zone_name);
393 int ret = zoneparams.init(cct, sysobj_svc);
394 if (ret < 0 && ret != -ENOENT) {
395 ldout(cct, 0) << __func__ << ": error initializing default zone params: " << cpp_strerror(-ret) << dendl;
396 return ret;
397 }
398 /* update master zone */
399 RGWZoneGroup default_zg(default_zonegroup_name);
400 ret = default_zg.init(cct, sysobj_svc);
401 if (ret < 0 && ret != -ENOENT) {
402 ldout(cct, 0) << __func__ << ": error in initializing default zonegroup: " << cpp_strerror(-ret) << dendl;
403 return ret;
404 }
405 if (ret != -ENOENT && default_zg.master_zone.empty()) {
406 default_zg.master_zone = zoneparams.get_id();
407 return default_zg.update();
408 }
409 return 0;
410 }
411
9f95a23c
TL
412 string master_region;
413 rgw_zone_id master_zone;
11fdf7f2
TL
414 for (list<string>::iterator iter = regions.begin(); iter != regions.end(); ++iter) {
415 if (*iter != default_zonegroup_name){
416 RGWZoneGroup region(*iter);
417 int ret = region.init(cct, sysobj_svc, true, true);
418 if (ret < 0) {
419 ldout(cct, 0) << __func__ << " failed init region "<< *iter << ": " << cpp_strerror(-ret) << dendl;
420 return ret;
421 }
422 if (region.is_master_zonegroup()) {
423 master_region = region.get_id();
424 master_zone = region.master_zone;
425 }
426 }
427 }
428
429 /* create realm if there is none.
430 The realm name will be the region and zone concatenated
431 realm id will be mds of its name */
432 if (realm->get_id().empty() && !master_region.empty() && !master_zone.empty()) {
9f95a23c 433 string new_realm_name = master_region + "." + master_zone.id;
11fdf7f2
TL
434 unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
435 char md5_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
436 MD5 hash;
437 hash.Update((const unsigned char *)new_realm_name.c_str(), new_realm_name.length());
438 hash.Final(md5);
439 buf_to_hex(md5, CEPH_CRYPTO_MD5_DIGESTSIZE, md5_str);
440 string new_realm_id(md5_str);
441 RGWRealm new_realm(new_realm_id,new_realm_name);
442 ret = new_realm.init(cct, sysobj_svc, false);
443 if (ret < 0) {
444 ldout(cct, 0) << __func__ << " Error initing new realm: " << cpp_strerror(-ret) << dendl;
445 return ret;
446 }
447 ret = new_realm.create();
448 if (ret < 0 && ret != -EEXIST) {
449 ldout(cct, 0) << __func__ << " Error creating new realm: " << cpp_strerror(-ret) << dendl;
450 return ret;
451 }
452 ret = new_realm.set_as_default();
453 if (ret < 0) {
454 ldout(cct, 0) << __func__ << " Error setting realm as default: " << cpp_strerror(-ret) << dendl;
455 return ret;
456 }
457 ret = realm->init(cct, sysobj_svc);
458 if (ret < 0) {
459 ldout(cct, 0) << __func__ << " Error initing realm: " << cpp_strerror(-ret) << dendl;
460 return ret;
461 }
462 ret = current_period->init(cct, sysobj_svc, realm->get_id(), realm->get_name());
463 if (ret < 0) {
464 ldout(cct, 0) << __func__ << " Error initing current period: " << cpp_strerror(-ret) << dendl;
465 return ret;
466 }
467 }
468
469 list<string>::iterator iter;
470 /* create zonegroups */
471 for (iter = regions.begin(); iter != regions.end(); ++iter)
472 {
473 ldout(cct, 0) << __func__ << " Converting " << *iter << dendl;
474 /* check to see if we don't have already a zonegroup with this name */
475 RGWZoneGroup new_zonegroup(*iter);
476 ret = new_zonegroup.init(cct , sysobj_svc);
477 if (ret == 0 && new_zonegroup.get_id() != *iter) {
478 ldout(cct, 0) << __func__ << " zonegroup "<< *iter << " already exists id " << new_zonegroup.get_id () <<
479 " skipping conversion " << dendl;
480 continue;
481 }
482 RGWZoneGroup zonegroup(*iter);
483 zonegroup.set_id(*iter);
484 int ret = zonegroup.init(cct, sysobj_svc, true, true);
485 if (ret < 0) {
486 ldout(cct, 0) << __func__ << " failed init zonegroup: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
487 return ret;
488 }
489 zonegroup.realm_id = realm->get_id();
490 /* fix default region master zone */
491 if (*iter == default_zonegroup_name && zonegroup.master_zone.empty()) {
492 ldout(cct, 0) << __func__ << " Setting default zone as master for default region" << dendl;
493 zonegroup.master_zone = default_zone_name;
494 }
495 ret = zonegroup.update();
496 if (ret < 0 && ret != -EEXIST) {
497 ldout(cct, 0) << __func__ << " failed to update zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret)
498 << dendl;
499 return ret;
500 }
501 ret = zonegroup.update_name();
502 if (ret < 0 && ret != -EEXIST) {
503 ldout(cct, 0) << __func__ << " failed to update_name for zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret)
504 << dendl;
505 return ret;
506 }
507 if (zonegroup.get_name() == default_region) {
508 ret = zonegroup.set_as_default();
509 if (ret < 0) {
510 ldout(cct, 0) << __func__ << " failed to set_as_default " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret)
511 << dendl;
512 return ret;
513 }
514 }
9f95a23c 515 for (auto iter = zonegroup.zones.begin(); iter != zonegroup.zones.end();
11fdf7f2
TL
516 ++iter) {
517 ldout(cct, 0) << __func__ << " Converting zone" << iter->first << dendl;
9f95a23c
TL
518 RGWZoneParams zoneparams(iter->first, iter->second.name);
519 zoneparams.set_id(iter->first.id);
11fdf7f2
TL
520 zoneparams.realm_id = realm->get_id();
521 ret = zoneparams.init(cct, sysobj_svc);
522 if (ret < 0 && ret != -ENOENT) {
523 ldout(cct, 0) << __func__ << " failed to init zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl;
524 return ret;
525 } else if (ret == -ENOENT) {
526 ldout(cct, 0) << __func__ << " zone is part of another cluster " << iter->first << " skipping " << dendl;
527 continue;
528 }
529 zonegroup.realm_id = realm->get_id();
530 ret = zoneparams.update();
531 if (ret < 0 && ret != -EEXIST) {
532 ldout(cct, 0) << __func__ << " failed to update zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl;
533 return ret;
534 }
535 ret = zoneparams.update_name();
536 if (ret < 0 && ret != -EEXIST) {
537 ldout(cct, 0) << __func__ << " failed to init zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl;
538 return ret;
539 }
540 }
541
542 if (!current_period->get_id().empty()) {
543 ret = current_period->add_zonegroup(zonegroup);
544 if (ret < 0) {
545 ldout(cct, 0) << __func__ << " failed to add zonegroup to current_period: " << cpp_strerror(-ret) << dendl;
546 return ret;
547 }
548 }
549 }
550
551 if (!current_period->get_id().empty()) {
552 ret = current_period->update();
553 if (ret < 0) {
554 ldout(cct, 0) << __func__ << " failed to update new period: " << cpp_strerror(-ret) << dendl;
555 return ret;
556 }
557 ret = current_period->store_info(false);
558 if (ret < 0) {
559 ldout(cct, 0) << __func__ << " failed to store new period: " << cpp_strerror(-ret) << dendl;
560 return ret;
561 }
562 ret = current_period->reflect();
563 if (ret < 0) {
564 ldout(cct, 0) << __func__ << " failed to update local objects: " << cpp_strerror(-ret) << dendl;
565 return ret;
566 }
567 }
568
569 for (auto const& iter : regions) {
570 RGWZoneGroup zonegroup(iter);
571 int ret = zonegroup.init(cct, sysobj_svc, true, true);
572 if (ret < 0) {
573 ldout(cct, 0) << __func__ << " failed init zonegroup" << iter << ": ret "<< ret << " " << cpp_strerror(-ret) << dendl;
574 return ret;
575 }
576 ret = zonegroup.delete_obj(true);
577 if (ret < 0 && ret != -ENOENT) {
578 ldout(cct, 0) << __func__ << " failed to delete region " << iter << ": ret "<< ret << " " << cpp_strerror(-ret)
579 << dendl;
580 return ret;
581 }
582 }
583
584 /* mark as converted */
585 ret = sysobj.wop()
586 .set_exclusive(true)
9f95a23c 587 .write(bl, null_yield);
11fdf7f2
TL
588 if (ret < 0 ) {
589 ldout(cct, 0) << __func__ << " failed to mark cluster as converted: ret "<< ret << " " << cpp_strerror(-ret)
590 << dendl;
591 return ret;
592 }
593
594 return 0;
595}
596
597/**
598 * Add new connection to connections map
599 * @param zonegroup_conn_map map which new connection will be added to
600 * @param zonegroup zonegroup which new connection will connect to
601 * @param new_connection pointer to new connection instance
602 */
603static void add_new_connection_to_map(map<string, RGWRESTConn *> &zonegroup_conn_map,
604 const RGWZoneGroup &zonegroup, RGWRESTConn *new_connection)
605{
606 // Delete if connection is already exists
607 map<string, RGWRESTConn *>::iterator iterZoneGroup = zonegroup_conn_map.find(zonegroup.get_id());
608 if (iterZoneGroup != zonegroup_conn_map.end()) {
609 delete iterZoneGroup->second;
610 }
611
612 // Add new connection to connections map
613 zonegroup_conn_map[zonegroup.get_id()] = new_connection;
614}
615
616int RGWSI_Zone::init_zg_from_period(bool *initialized)
617{
618 *initialized = false;
619
620 if (current_period->get_id().empty()) {
621 return 0;
622 }
623
624 int ret = zonegroup->init(cct, sysobj_svc);
625 ldout(cct, 20) << "period zonegroup init ret " << ret << dendl;
626 if (ret == -ENOENT) {
627 return 0;
628 }
629 if (ret < 0) {
630 ldout(cct, 0) << "failed reading zonegroup info: " << cpp_strerror(-ret) << dendl;
631 return ret;
632 }
633 ldout(cct, 20) << "period zonegroup name " << zonegroup->get_name() << dendl;
634
635 map<string, RGWZoneGroup>::const_iterator iter =
636 current_period->get_map().zonegroups.find(zonegroup->get_id());
637
638 if (iter != current_period->get_map().zonegroups.end()) {
639 ldout(cct, 20) << "using current period zonegroup " << zonegroup->get_name() << dendl;
640 *zonegroup = iter->second;
641 ret = zonegroup->init(cct, sysobj_svc, false);
642 if (ret < 0) {
643 ldout(cct, 0) << "failed init zonegroup: " << " " << cpp_strerror(-ret) << dendl;
644 return ret;
645 }
646 ret = zone_params->init(cct, sysobj_svc);
647 if (ret < 0 && ret != -ENOENT) {
648 ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl;
649 return ret;
650 } if (ret ==-ENOENT && zonegroup->get_name() == default_zonegroup_name) {
651 ldout(cct, 10) << " Using default name "<< default_zone_name << dendl;
652 zone_params->set_name(default_zone_name);
653 ret = zone_params->init(cct, sysobj_svc);
654 if (ret < 0 && ret != -ENOENT) {
655 ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl;
656 return ret;
657 }
658 }
659 }
660 for (iter = current_period->get_map().zonegroups.begin();
661 iter != current_period->get_map().zonegroups.end(); ++iter){
662 const RGWZoneGroup& zg = iter->second;
663 // use endpoints from the zonegroup's master zone
664 auto master = zg.zones.find(zg.master_zone);
665 if (master == zg.zones.end()) {
666 // Check for empty zonegroup which can happen if zone was deleted before removal
667 if (zg.zones.size() == 0)
668 continue;
669 // fix missing master zone for a single zone zonegroup
670 if (zg.master_zone.empty() && zg.zones.size() == 1) {
671 master = zg.zones.begin();
672 ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing master_zone, setting zone " <<
673 master->second.name << " id:" << master->second.id << " as master" << dendl;
674 if (zonegroup->get_id() == zg.get_id()) {
675 zonegroup->master_zone = master->second.id;
676 ret = zonegroup->update();
677 if (ret < 0) {
678 ldout(cct, 0) << "error updating zonegroup : " << cpp_strerror(-ret) << dendl;
679 return ret;
680 }
681 } else {
682 RGWZoneGroup fixed_zg(zg.get_id(),zg.get_name());
683 ret = fixed_zg.init(cct, sysobj_svc);
684 if (ret < 0) {
685 ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl;
686 return ret;
687 }
688 fixed_zg.master_zone = master->second.id;
689 ret = fixed_zg.update();
690 if (ret < 0) {
691 ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl;
692 return ret;
693 }
694 }
695 } else {
696 ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing zone for master_zone=" <<
697 zg.master_zone << dendl;
698 return -EINVAL;
699 }
700 }
701 const auto& endpoints = master->second.endpoints;
702 add_new_connection_to_map(zonegroup_conn_map, zg, new RGWRESTConn(cct, this, zg.get_id(), endpoints));
703 if (!current_period->get_master_zonegroup().empty() &&
704 zg.get_id() == current_period->get_master_zonegroup()) {
705 rest_master_conn = new RGWRESTConn(cct, this, zg.get_id(), endpoints);
706 }
707 }
708
709 *initialized = true;
710
711 return 0;
712}
713
714int RGWSI_Zone::init_zg_from_local(bool *creating_defaults)
715{
716 int ret = zonegroup->init(cct, sysobj_svc);
717 if ( (ret < 0 && ret != -ENOENT) || (ret == -ENOENT && !cct->_conf->rgw_zonegroup.empty())) {
718 ldout(cct, 0) << "failed reading zonegroup info: ret "<< ret << " " << cpp_strerror(-ret) << dendl;
719 return ret;
720 } else if (ret == -ENOENT) {
721 *creating_defaults = true;
722 ldout(cct, 10) << "Creating default zonegroup " << dendl;
723 ret = zonegroup->create_default();
724 if (ret < 0) {
725 ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret)
726 << dendl;
727 return ret;
728 }
729 ret = zonegroup->init(cct, sysobj_svc);
730 if (ret < 0) {
731 ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret)
732 << dendl;
733 return ret;
734 }
735 }
736 ldout(cct, 20) << "zonegroup " << zonegroup->get_name() << dendl;
737 if (zonegroup->is_master_zonegroup()) {
738 // use endpoints from the zonegroup's master zone
739 auto master = zonegroup->zones.find(zonegroup->master_zone);
740 if (master == zonegroup->zones.end()) {
741 // fix missing master zone for a single zone zonegroup
742 if (zonegroup->master_zone.empty() && zonegroup->zones.size() == 1) {
743 master = zonegroup->zones.begin();
744 ldout(cct, 0) << "zonegroup " << zonegroup->get_name() << " missing master_zone, setting zone " <<
745 master->second.name << " id:" << master->second.id << " as master" << dendl;
746 zonegroup->master_zone = master->second.id;
747 ret = zonegroup->update();
748 if (ret < 0) {
749 ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl;
750 return ret;
751 }
752 } else {
753 ldout(cct, 0) << "zonegroup " << zonegroup->get_name() << " missing zone for "
754 "master_zone=" << zonegroup->master_zone << dendl;
755 return -EINVAL;
756 }
757 }
758 const auto& endpoints = master->second.endpoints;
759 rest_master_conn = new RGWRESTConn(cct, this, zonegroup->get_id(), endpoints);
760 }
761
762 return 0;
763}
764
765int RGWSI_Zone::convert_regionmap()
766{
767 RGWZoneGroupMap zonegroupmap;
768
769 string pool_name = cct->_conf->rgw_zone_root_pool;
770 if (pool_name.empty()) {
771 pool_name = RGW_DEFAULT_ZONE_ROOT_POOL;
772 }
773 string oid = region_map_oid;
774
775 rgw_pool pool(pool_name);
776 bufferlist bl;
777
778 RGWSysObjectCtx obj_ctx = sysobj_svc->init_obj_ctx();
779 RGWSysObj sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid));
780
9f95a23c 781 int ret = sysobj.rop().read(&bl, null_yield);
11fdf7f2
TL
782 if (ret < 0 && ret != -ENOENT) {
783 return ret;
784 } else if (ret == -ENOENT) {
785 return 0;
786 }
787
788 try {
789 auto iter = bl.cbegin();
790 decode(zonegroupmap, iter);
791 } catch (buffer::error& err) {
792 ldout(cct, 0) << "error decoding regionmap from " << pool << ":" << oid << dendl;
793 return -EIO;
794 }
795
796 for (map<string, RGWZoneGroup>::iterator iter = zonegroupmap.zonegroups.begin();
797 iter != zonegroupmap.zonegroups.end(); ++iter) {
798 RGWZoneGroup& zonegroup = iter->second;
799 ret = zonegroup.init(cct, sysobj_svc, false);
800 ret = zonegroup.update();
801 if (ret < 0 && ret != -ENOENT) {
802 ldout(cct, 0) << "Error could not update zonegroup " << zonegroup.get_name() << ": " <<
803 cpp_strerror(-ret) << dendl;
804 return ret;
805 } else if (ret == -ENOENT) {
806 ret = zonegroup.create();
807 if (ret < 0) {
808 ldout(cct, 0) << "Error could not create " << zonegroup.get_name() << ": " <<
809 cpp_strerror(-ret) << dendl;
810 return ret;
811 }
812 }
813 }
814
815 current_period->set_user_quota(zonegroupmap.user_quota);
816 current_period->set_bucket_quota(zonegroupmap.bucket_quota);
817
818 // remove the region_map so we don't try to convert again
9f95a23c 819 ret = sysobj.wop().remove(null_yield);
11fdf7f2
TL
820 if (ret < 0) {
821 ldout(cct, 0) << "Error could not remove " << sysobj.get_obj()
822 << " after upgrading to zonegroup map: " << cpp_strerror(ret) << dendl;
823 return ret;
824 }
825
826 return 0;
827}
828
829const RGWZoneParams& RGWSI_Zone::get_zone_params() const
830{
831 return *zone_params;
832}
833
834const RGWZone& RGWSI_Zone::get_zone() const
835{
836 return *zone_public_config;
837}
838
839const RGWZoneGroup& RGWSI_Zone::get_zonegroup() const
840{
841 return *zonegroup;
842}
843
844int RGWSI_Zone::get_zonegroup(const string& id, RGWZoneGroup& zg) const
845{
846 int ret = 0;
847 if (id == zonegroup->get_id()) {
848 zg = *zonegroup;
849 } else if (!current_period->get_id().empty()) {
850 ret = current_period->get_zonegroup(zg, id);
851 }
852 return ret;
853}
854
855const RGWRealm& RGWSI_Zone::get_realm() const
856{
857 return *realm;
858}
859
860const RGWPeriod& RGWSI_Zone::get_current_period() const
861{
862 return *current_period;
863}
864
9f95a23c 865const string& RGWSI_Zone::get_current_period_id() const
11fdf7f2
TL
866{
867 return current_period->get_id();
868}
869
870bool RGWSI_Zone::has_zonegroup_api(const std::string& api) const
871{
872 if (!current_period->get_id().empty()) {
873 const auto& zonegroups_by_api = current_period->get_map().zonegroups_by_api;
874 if (zonegroups_by_api.find(api) != zonegroups_by_api.end())
875 return true;
876 } else if (zonegroup->api_name == api) {
877 return true;
878 }
879 return false;
880}
881
882bool RGWSI_Zone::zone_is_writeable()
883{
884 return writeable_zone && !get_zone().is_read_only();
885}
886
887uint32_t RGWSI_Zone::get_zone_short_id() const
888{
889 return zone_short_id;
890}
891
9f95a23c 892const string& RGWSI_Zone::zone_name() const
11fdf7f2
TL
893{
894 return get_zone_params().get_name();
895}
11fdf7f2 896
9f95a23c 897bool RGWSI_Zone::find_zone(const rgw_zone_id& id, RGWZone **zone)
11fdf7f2
TL
898{
899 auto iter = zone_by_id.find(id);
900 if (iter == zone_by_id.end()) {
901 return false;
902 }
903 *zone = &(iter->second);
904 return true;
905}
906
9f95a23c
TL
907RGWRESTConn *RGWSI_Zone::get_zone_conn(const rgw_zone_id& zone_id) {
908 auto citer = zone_conn_map.find(zone_id.id);
11fdf7f2
TL
909 if (citer == zone_conn_map.end()) {
910 return NULL;
911 }
912
913 return citer->second;
914}
915
916RGWRESTConn *RGWSI_Zone::get_zone_conn_by_name(const string& name) {
917 auto i = zone_id_by_name.find(name);
918 if (i == zone_id_by_name.end()) {
919 return NULL;
920 }
921
9f95a23c 922 return get_zone_conn(i->second);
11fdf7f2
TL
923}
924
9f95a23c 925bool RGWSI_Zone::find_zone_id_by_name(const string& name, rgw_zone_id *id) {
11fdf7f2
TL
926 auto i = zone_id_by_name.find(name);
927 if (i == zone_id_by_name.end()) {
928 return false;
929 }
930 *id = i->second;
931 return true;
932}
933
9f95a23c
TL
934bool RGWSI_Zone::need_to_sync() const
935{
936 return !(zonegroup->master_zone.empty() ||
937 !rest_master_conn ||
938 current_period->get_id().empty());
939}
940
11fdf7f2
TL
941bool RGWSI_Zone::need_to_log_data() const
942{
943 return zone_public_config->log_data;
944}
945
946bool RGWSI_Zone::is_meta_master() const
947{
948 if (!zonegroup->is_master_zonegroup()) {
949 return false;
950 }
951
952 return (zonegroup->master_zone == zone_public_config->id);
953}
954
955bool RGWSI_Zone::need_to_log_metadata() const
956{
957 return is_meta_master() &&
958 (zonegroup->zones.size() > 1 || current_period->is_multi_zonegroups_with_zones());
959}
960
961bool RGWSI_Zone::can_reshard() const
962{
963 return current_period->get_id().empty() ||
964 (zonegroup->zones.size() == 1 && current_period->is_single_zonegroup());
965}
966
967/**
968 * Check to see if the bucket metadata could be synced
969 * bucket: the bucket to check
970 * Returns false is the bucket is not synced
971 */
972bool RGWSI_Zone::is_syncing_bucket_meta(const rgw_bucket& bucket)
973{
974
975 /* no current period */
976 if (current_period->get_id().empty()) {
977 return false;
978 }
979
980 /* zonegroup is not master zonegroup */
981 if (!zonegroup->is_master_zonegroup()) {
982 return false;
983 }
984
985 /* single zonegroup and a single zone */
986 if (current_period->is_single_zonegroup() && zonegroup->zones.size() == 1) {
987 return false;
988 }
989
990 /* zone is not master */
9f95a23c 991 if (zonegroup->master_zone != zone_public_config->id) {
11fdf7f2
TL
992 return false;
993 }
994
995 return true;
996}
997
998
999int RGWSI_Zone::select_new_bucket_location(const RGWUserInfo& user_info, const string& zonegroup_id,
1000 const rgw_placement_rule& request_rule,
1001 rgw_placement_rule *pselected_rule_name, RGWZonePlacementInfo *rule_info)
1002{
1003 /* first check that zonegroup exists within current period. */
1004 RGWZoneGroup zonegroup;
1005 int ret = get_zonegroup(zonegroup_id, zonegroup);
1006 if (ret < 0) {
1007 ldout(cct, 0) << "could not find zonegroup " << zonegroup_id << " in current period" << dendl;
1008 return ret;
1009 }
1010
1011 const rgw_placement_rule *used_rule;
1012
1013 /* find placement rule. Hierarchy: request rule > user default rule > zonegroup default rule */
1014 std::map<std::string, RGWZoneGroupPlacementTarget>::const_iterator titer;
1015
1016 if (!request_rule.name.empty()) {
1017 used_rule = &request_rule;
1018 titer = zonegroup.placement_targets.find(request_rule.name);
1019 if (titer == zonegroup.placement_targets.end()) {
1020 ldout(cct, 0) << "could not find requested placement id " << request_rule
1021 << " within zonegroup " << dendl;
1022 return -ERR_INVALID_LOCATION_CONSTRAINT;
1023 }
1024 } else if (!user_info.default_placement.name.empty()) {
1025 used_rule = &user_info.default_placement;
1026 titer = zonegroup.placement_targets.find(user_info.default_placement.name);
1027 if (titer == zonegroup.placement_targets.end()) {
1028 ldout(cct, 0) << "could not find user default placement id " << user_info.default_placement
1029 << " within zonegroup " << dendl;
1030 return -ERR_INVALID_LOCATION_CONSTRAINT;
1031 }
1032 } else {
1033 if (zonegroup.default_placement.name.empty()) { // zonegroup default rule as fallback, it should not be empty.
1034 ldout(cct, 0) << "misconfiguration, zonegroup default placement id should not be empty." << dendl;
1035 return -ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION;
1036 } else {
1037 used_rule = &zonegroup.default_placement;
1038 titer = zonegroup.placement_targets.find(zonegroup.default_placement.name);
1039 if (titer == zonegroup.placement_targets.end()) {
1040 ldout(cct, 0) << "could not find zonegroup default placement id " << zonegroup.default_placement
1041 << " within zonegroup " << dendl;
1042 return -ERR_INVALID_LOCATION_CONSTRAINT;
1043 }
1044 }
1045 }
1046
1047 /* now check tag for the rule, whether user is permitted to use rule */
1048 const auto& target_rule = titer->second;
1049 if (!target_rule.user_permitted(user_info.placement_tags)) {
1050 ldout(cct, 0) << "user not permitted to use placement rule " << titer->first << dendl;
1051 return -EPERM;
1052 }
1053
1054 const string *storage_class = &request_rule.storage_class;
1055
1056 if (storage_class->empty()) {
1057 storage_class = &used_rule->storage_class;
1058 }
1059
1060 rgw_placement_rule rule(titer->first, *storage_class);
1061
1062 if (pselected_rule_name) {
1063 *pselected_rule_name = rule;
1064 }
1065
1066 return select_bucket_location_by_rule(rule, rule_info);
1067}
1068
1069int RGWSI_Zone::select_bucket_location_by_rule(const rgw_placement_rule& location_rule, RGWZonePlacementInfo *rule_info)
1070{
1071 if (location_rule.name.empty()) {
1072 /* we can only reach here if we're trying to set a bucket location from a bucket
1073 * created on a different zone, using a legacy / default pool configuration
1074 */
1075 if (rule_info) {
1076 return select_legacy_bucket_placement(rule_info);
1077 }
1078
1079 return 0;
1080 }
1081
1082 /*
1083 * make sure that zone has this rule configured. We're
1084 * checking it for the local zone, because that's where this bucket object is going to
1085 * reside.
1086 */
1087 auto piter = zone_params->placement_pools.find(location_rule.name);
1088 if (piter == zone_params->placement_pools.end()) {
1089 /* couldn't find, means we cannot really place data for this bucket in this zone */
1090 ldout(cct, 0) << "ERROR: This zone does not contain placement rule "
1091 << location_rule << " present in the zonegroup!" << dendl;
1092 return -EINVAL;
1093 }
1094
1095 auto storage_class = location_rule.get_storage_class();
1096 if (!piter->second.storage_class_exists(storage_class)) {
1097 ldout(cct, 5) << "requested storage class does not exist: " << storage_class << dendl;
1098 return -EINVAL;
1099 }
1100
1101
1102 RGWZonePlacementInfo& placement_info = piter->second;
1103
1104 if (rule_info) {
1105 *rule_info = placement_info;
1106 }
1107
1108 return 0;
1109}
1110
1111int RGWSI_Zone::select_bucket_placement(const RGWUserInfo& user_info, const string& zonegroup_id,
1112 const rgw_placement_rule& placement_rule,
1113 rgw_placement_rule *pselected_rule, RGWZonePlacementInfo *rule_info)
1114{
1115 if (!zone_params->placement_pools.empty()) {
1116 return select_new_bucket_location(user_info, zonegroup_id, placement_rule,
1117 pselected_rule, rule_info);
1118 }
1119
1120 if (pselected_rule) {
1121 pselected_rule->clear();
1122 }
1123
1124 if (rule_info) {
1125 return select_legacy_bucket_placement(rule_info);
1126 }
1127
1128 return 0;
1129}
1130
1131int RGWSI_Zone::select_legacy_bucket_placement(RGWZonePlacementInfo *rule_info)
1132{
1133 bufferlist map_bl;
1134 map<string, bufferlist> m;
1135 string pool_name;
1136 bool write_map = false;
1137
1138 rgw_raw_obj obj(zone_params->domain_root, avail_pools);
1139
1140 auto obj_ctx = sysobj_svc->init_obj_ctx();
1141 auto sysobj = obj_ctx.get_obj(obj);
1142
9f95a23c 1143 int ret = sysobj.rop().read(&map_bl, null_yield);
11fdf7f2
TL
1144 if (ret < 0) {
1145 goto read_omap;
1146 }
1147
1148 try {
1149 auto iter = map_bl.cbegin();
1150 decode(m, iter);
1151 } catch (buffer::error& err) {
1152 ldout(cct, 0) << "ERROR: couldn't decode avail_pools" << dendl;
1153 }
1154
1155read_omap:
1156 if (m.empty()) {
9f95a23c 1157 ret = sysobj.omap().get_all(&m, null_yield);
11fdf7f2
TL
1158
1159 write_map = true;
1160 }
1161
1162 if (ret < 0 || m.empty()) {
1163 vector<rgw_pool> pools;
1164 string s = string("default.") + default_storage_pool_suffix;
1165 pools.push_back(rgw_pool(s));
1166 vector<int> retcodes;
1167 bufferlist bl;
1168 ret = rados_svc->pool().create(pools, &retcodes);
1169 if (ret < 0)
1170 return ret;
9f95a23c 1171 ret = sysobj.omap().set(s, bl, null_yield);
11fdf7f2
TL
1172 if (ret < 0)
1173 return ret;
1174 m[s] = bl;
1175 }
1176
1177 if (write_map) {
1178 bufferlist new_bl;
1179 encode(m, new_bl);
9f95a23c 1180 ret = sysobj.wop().write(new_bl, null_yield);
11fdf7f2
TL
1181 if (ret < 0) {
1182 ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
1183 }
1184 }
1185
1186 auto miter = m.begin();
1187 if (m.size() > 1) {
1188 // choose a pool at random
1189 auto r = ceph::util::generate_random_number<size_t>(0, m.size() - 1);
1190 std::advance(miter, r);
1191 }
1192 pool_name = miter->first;
1193
1194 rgw_pool pool = pool_name;
1195
1196 rule_info->storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &pool, nullptr);
1197 rule_info->data_extra_pool = pool_name;
1198 rule_info->index_pool = pool_name;
1199 rule_info->index_type = RGWBIType_Normal;
1200
1201 return 0;
1202}
1203
1204int RGWSI_Zone::update_placement_map()
1205{
1206 bufferlist header;
1207 map<string, bufferlist> m;
1208 rgw_raw_obj obj(zone_params->domain_root, avail_pools);
1209
1210 auto obj_ctx = sysobj_svc->init_obj_ctx();
1211 auto sysobj = obj_ctx.get_obj(obj);
1212
9f95a23c 1213 int ret = sysobj.omap().get_all(&m, null_yield);
11fdf7f2
TL
1214 if (ret < 0)
1215 return ret;
1216
1217 bufferlist new_bl;
1218 encode(m, new_bl);
9f95a23c 1219 ret = sysobj.wop().write(new_bl, null_yield);
11fdf7f2
TL
1220 if (ret < 0) {
1221 ldout(cct, 0) << "WARNING: could not save avail pools map info ret=" << ret << dendl;
1222 }
1223
1224 return ret;
1225}
1226
1227int RGWSI_Zone::add_bucket_placement(const rgw_pool& new_pool)
1228{
1229 int ret = rados_svc->pool(new_pool).lookup();
1230 if (ret < 0) { // DNE, or something
1231 return ret;
1232 }
1233
1234 rgw_raw_obj obj(zone_params->domain_root, avail_pools);
1235 auto obj_ctx = sysobj_svc->init_obj_ctx();
1236 auto sysobj = obj_ctx.get_obj(obj);
1237
1238 bufferlist empty_bl;
9f95a23c 1239 ret = sysobj.omap().set(new_pool.to_str(), empty_bl, null_yield);
11fdf7f2
TL
1240
1241 // don't care about return value
1242 update_placement_map();
1243
1244 return ret;
1245}
1246
1247int RGWSI_Zone::remove_bucket_placement(const rgw_pool& old_pool)
1248{
1249 rgw_raw_obj obj(zone_params->domain_root, avail_pools);
1250 auto obj_ctx = sysobj_svc->init_obj_ctx();
1251 auto sysobj = obj_ctx.get_obj(obj);
1252
9f95a23c 1253 int ret = sysobj.omap().del(old_pool.to_str(), null_yield);
11fdf7f2
TL
1254
1255 // don't care about return value
1256 update_placement_map();
1257
1258 return ret;
1259}
1260
1261int RGWSI_Zone::list_placement_set(set<rgw_pool>& names)
1262{
1263 bufferlist header;
1264 map<string, bufferlist> m;
1265
1266 rgw_raw_obj obj(zone_params->domain_root, avail_pools);
1267 auto obj_ctx = sysobj_svc->init_obj_ctx();
1268 auto sysobj = obj_ctx.get_obj(obj);
9f95a23c 1269 int ret = sysobj.omap().get_all(&m, null_yield);
11fdf7f2
TL
1270 if (ret < 0)
1271 return ret;
1272
1273 names.clear();
1274 map<string, bufferlist>::iterator miter;
1275 for (miter = m.begin(); miter != m.end(); ++miter) {
1276 names.insert(rgw_pool(miter->first));
1277 }
1278
1279 return names.size();
1280}
1281
1282bool RGWSI_Zone::get_redirect_zone_endpoint(string *endpoint)
1283{
1284 if (zone_public_config->redirect_zone.empty()) {
1285 return false;
1286 }
1287
1288 auto iter = zone_conn_map.find(zone_public_config->redirect_zone);
1289 if (iter == zone_conn_map.end()) {
1290 ldout(cct, 0) << "ERROR: cannot find entry for redirect zone: " << zone_public_config->redirect_zone << dendl;
1291 return false;
1292 }
1293
1294 RGWRESTConn *conn = iter->second;
1295
1296 int ret = conn->get_url(*endpoint);
1297 if (ret < 0) {
1298 ldout(cct, 0) << "ERROR: redirect zone, conn->get_endpoint() returned ret=" << ret << dendl;
1299 return false;
1300 }
1301
1302 return true;
1303}
1304