]>
Commit | Line | Data |
---|---|---|
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 | ||
18 | using namespace rgw_zone_defaults; | |
19 | ||
20 | RGWSI_Zone::RGWSI_Zone(CephContext *cct) : RGWServiceInstance(cct) | |
21 | { | |
22 | } | |
23 | ||
24 | void 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 | ||
41 | RGWSI_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 |
50 | std::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 |
61 | bool 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 | ||
67 | int 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 | ||
254 | void 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 | ||
269 | int 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, ®ions); |
11fdf7f2 TL |
275 | } |
276 | ||
277 | int 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 | ||
285 | int 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 | ||
293 | int 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 | ||
301 | int 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 | ||
324 | int 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 | */ | |
346 | int 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 | */ | |
603 | static 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 | ||
616 | int 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 | ||
714 | int 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 | ||
765 | int 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 | ||
829 | const RGWZoneParams& RGWSI_Zone::get_zone_params() const | |
830 | { | |
831 | return *zone_params; | |
832 | } | |
833 | ||
834 | const RGWZone& RGWSI_Zone::get_zone() const | |
835 | { | |
836 | return *zone_public_config; | |
837 | } | |
838 | ||
839 | const RGWZoneGroup& RGWSI_Zone::get_zonegroup() const | |
840 | { | |
841 | return *zonegroup; | |
842 | } | |
843 | ||
844 | int 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 | ||
855 | const RGWRealm& RGWSI_Zone::get_realm() const | |
856 | { | |
857 | return *realm; | |
858 | } | |
859 | ||
860 | const RGWPeriod& RGWSI_Zone::get_current_period() const | |
861 | { | |
862 | return *current_period; | |
863 | } | |
864 | ||
9f95a23c | 865 | const string& RGWSI_Zone::get_current_period_id() const |
11fdf7f2 TL |
866 | { |
867 | return current_period->get_id(); | |
868 | } | |
869 | ||
870 | bool 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 | ||
882 | bool RGWSI_Zone::zone_is_writeable() | |
883 | { | |
884 | return writeable_zone && !get_zone().is_read_only(); | |
885 | } | |
886 | ||
887 | uint32_t RGWSI_Zone::get_zone_short_id() const | |
888 | { | |
889 | return zone_short_id; | |
890 | } | |
891 | ||
9f95a23c | 892 | const string& RGWSI_Zone::zone_name() const |
11fdf7f2 TL |
893 | { |
894 | return get_zone_params().get_name(); | |
895 | } | |
11fdf7f2 | 896 | |
9f95a23c | 897 | bool 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 |
907 | RGWRESTConn *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 | ||
916 | RGWRESTConn *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 | 925 | bool 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 |
934 | bool 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 |
941 | bool RGWSI_Zone::need_to_log_data() const |
942 | { | |
943 | return zone_public_config->log_data; | |
944 | } | |
945 | ||
946 | bool 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 | ||
955 | bool 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 | ||
961 | bool 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 | */ | |
972 | bool 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 | ||
999 | int 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 | ||
1069 | int 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 | ||
1111 | int 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 | ||
1131 | int 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 | ||
1155 | read_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 | ||
1204 | int 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 | ||
1227 | int 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 | ||
1247 | int 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 | ||
1261 | int 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 | ||
1282 | bool 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 |