]>
Commit | Line | Data |
---|---|---|
1e59de90 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 | ||
4 | #include <optional> | |
5 | ||
6 | #include "common/errno.h" | |
7 | ||
8 | #include "rgw_zone.h" | |
9 | #include "rgw_realm_watcher.h" | |
10 | #include "rgw_meta_sync_status.h" | |
11 | #include "rgw_sal_config.h" | |
12 | #include "rgw_string.h" | |
13 | #include "rgw_sync.h" | |
14 | ||
15 | #include "services/svc_zone.h" | |
16 | #include "services/svc_sys_obj.h" | |
17 | ||
18 | #include "common/ceph_json.h" | |
19 | #include "common/Formatter.h" | |
20 | ||
21 | #define dout_context g_ceph_context | |
22 | #define dout_subsys ceph_subsys_rgw | |
23 | ||
24 | namespace rgw_zone_defaults { | |
25 | ||
26 | std::string realm_info_oid_prefix = "realms."; | |
27 | std::string realm_names_oid_prefix = "realms_names."; | |
28 | std::string default_realm_info_oid = "default.realm"; | |
29 | std::string RGW_DEFAULT_REALM_ROOT_POOL = "rgw.root"; | |
30 | ||
31 | } | |
32 | ||
33 | using namespace std; | |
34 | using namespace rgw_zone_defaults; | |
35 | ||
36 | RGWRealm::~RGWRealm() {} | |
37 | ||
38 | RGWRemoteMetaLog::~RGWRemoteMetaLog() | |
39 | { | |
40 | delete error_logger; | |
41 | } | |
42 | ||
43 | string RGWRealm::get_predefined_id(CephContext *cct) const { | |
44 | return cct->_conf.get_val<string>("rgw_realm_id"); | |
45 | } | |
46 | ||
47 | const string& RGWRealm::get_predefined_name(CephContext *cct) const { | |
48 | return cct->_conf->rgw_realm; | |
49 | } | |
50 | ||
51 | int RGWRealm::create(const DoutPrefixProvider *dpp, optional_yield y, bool exclusive) | |
52 | { | |
53 | int ret = RGWSystemMetaObj::create(dpp, y, exclusive); | |
54 | if (ret < 0) { | |
55 | ldpp_dout(dpp, 0) << "ERROR creating new realm object " << name << ": " << cpp_strerror(-ret) << dendl; | |
56 | return ret; | |
57 | } | |
58 | // create the control object for watch/notify | |
59 | ret = create_control(dpp, exclusive, y); | |
60 | if (ret < 0) { | |
61 | ldpp_dout(dpp, 0) << "ERROR creating control for new realm " << name << ": " << cpp_strerror(-ret) << dendl; | |
62 | return ret; | |
63 | } | |
64 | RGWPeriod period; | |
65 | if (current_period.empty()) { | |
66 | /* create new period for the realm */ | |
67 | ret = period.init(dpp, cct, sysobj_svc, id, y, name, false); | |
68 | if (ret < 0 ) { | |
69 | return ret; | |
70 | } | |
71 | ret = period.create(dpp, y, true); | |
72 | if (ret < 0) { | |
73 | ldpp_dout(dpp, 0) << "ERROR: creating new period for realm " << name << ": " << cpp_strerror(-ret) << dendl; | |
74 | return ret; | |
75 | } | |
76 | } else { | |
77 | period = RGWPeriod(current_period, 0); | |
78 | int ret = period.init(dpp, cct, sysobj_svc, id, y, name); | |
79 | if (ret < 0) { | |
80 | ldpp_dout(dpp, 0) << "ERROR: failed to init period " << current_period << dendl; | |
81 | return ret; | |
82 | } | |
83 | } | |
84 | ret = set_current_period(dpp, period, y); | |
85 | if (ret < 0) { | |
86 | ldpp_dout(dpp, 0) << "ERROR: failed set current period " << current_period << dendl; | |
87 | return ret; | |
88 | } | |
89 | // try to set as default. may race with another create, so pass exclusive=true | |
90 | // so we don't override an existing default | |
91 | ret = set_as_default(dpp, y, true); | |
92 | if (ret < 0 && ret != -EEXIST) { | |
93 | ldpp_dout(dpp, 0) << "WARNING: failed to set realm as default realm, ret=" << ret << dendl; | |
94 | } | |
95 | ||
96 | return 0; | |
97 | } | |
98 | ||
99 | int RGWRealm::delete_obj(const DoutPrefixProvider *dpp, optional_yield y) | |
100 | { | |
101 | int ret = RGWSystemMetaObj::delete_obj(dpp, y); | |
102 | if (ret < 0) { | |
103 | return ret; | |
104 | } | |
105 | return delete_control(dpp, y); | |
106 | } | |
107 | ||
108 | int RGWRealm::create_control(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y) | |
109 | { | |
110 | auto pool = rgw_pool{get_pool(cct)}; | |
111 | auto oid = get_control_oid(); | |
112 | bufferlist bl; | |
113 | auto sysobj = sysobj_svc->get_obj(rgw_raw_obj{pool, oid}); | |
114 | return sysobj.wop() | |
115 | .set_exclusive(exclusive) | |
116 | .write(dpp, bl, y); | |
117 | } | |
118 | ||
119 | int RGWRealm::delete_control(const DoutPrefixProvider *dpp, optional_yield y) | |
120 | { | |
121 | auto pool = rgw_pool{get_pool(cct)}; | |
122 | auto obj = rgw_raw_obj{pool, get_control_oid()}; | |
123 | auto sysobj = sysobj_svc->get_obj(obj); | |
124 | return sysobj.wop().remove(dpp, y); | |
125 | } | |
126 | ||
127 | rgw_pool RGWRealm::get_pool(CephContext *cct) const | |
128 | { | |
129 | if (cct->_conf->rgw_realm_root_pool.empty()) { | |
130 | return rgw_pool(RGW_DEFAULT_REALM_ROOT_POOL); | |
131 | } | |
132 | return rgw_pool(cct->_conf->rgw_realm_root_pool); | |
133 | } | |
134 | ||
135 | const string RGWRealm::get_default_oid(bool old_format) const | |
136 | { | |
137 | if (cct->_conf->rgw_default_realm_info_oid.empty()) { | |
138 | return default_realm_info_oid; | |
139 | } | |
140 | return cct->_conf->rgw_default_realm_info_oid; | |
141 | } | |
142 | ||
143 | const string& RGWRealm::get_names_oid_prefix() const | |
144 | { | |
145 | return realm_names_oid_prefix; | |
146 | } | |
147 | ||
148 | const string& RGWRealm::get_info_oid_prefix(bool old_format) const | |
149 | { | |
150 | return realm_info_oid_prefix; | |
151 | } | |
152 | ||
153 | int RGWRealm::set_current_period(const DoutPrefixProvider *dpp, RGWPeriod& period, optional_yield y) | |
154 | { | |
155 | // update realm epoch to match the period's | |
156 | if (epoch > period.get_realm_epoch()) { | |
157 | ldpp_dout(dpp, 0) << "ERROR: set_current_period with old realm epoch " | |
158 | << period.get_realm_epoch() << ", current epoch=" << epoch << dendl; | |
159 | return -EINVAL; | |
160 | } | |
161 | if (epoch == period.get_realm_epoch() && current_period != period.get_id()) { | |
162 | ldpp_dout(dpp, 0) << "ERROR: set_current_period with same realm epoch " | |
163 | << period.get_realm_epoch() << ", but different period id " | |
164 | << period.get_id() << " != " << current_period << dendl; | |
165 | return -EINVAL; | |
166 | } | |
167 | ||
168 | epoch = period.get_realm_epoch(); | |
169 | current_period = period.get_id(); | |
170 | ||
171 | int ret = update(dpp, y); | |
172 | if (ret < 0) { | |
173 | ldpp_dout(dpp, 0) << "ERROR: period update: " << cpp_strerror(-ret) << dendl; | |
174 | return ret; | |
175 | } | |
176 | ||
177 | ret = period.reflect(dpp, y); | |
178 | if (ret < 0) { | |
179 | ldpp_dout(dpp, 0) << "ERROR: period.reflect(): " << cpp_strerror(-ret) << dendl; | |
180 | return ret; | |
181 | } | |
182 | ||
183 | return 0; | |
184 | } | |
185 | ||
186 | string RGWRealm::get_control_oid() const | |
187 | { | |
188 | return get_info_oid_prefix() + id + ".control"; | |
189 | } | |
190 | ||
191 | int RGWRealm::notify_zone(const DoutPrefixProvider *dpp, bufferlist& bl, optional_yield y) | |
192 | { | |
193 | rgw_pool pool{get_pool(cct)}; | |
194 | auto sysobj = sysobj_svc->get_obj(rgw_raw_obj{pool, get_control_oid()}); | |
195 | int ret = sysobj.wn().notify(dpp, bl, 0, nullptr, y); | |
196 | if (ret < 0) { | |
197 | return ret; | |
198 | } | |
199 | return 0; | |
200 | } | |
201 | ||
202 | int RGWRealm::notify_new_period(const DoutPrefixProvider *dpp, const RGWPeriod& period, optional_yield y) | |
203 | { | |
204 | bufferlist bl; | |
205 | using ceph::encode; | |
206 | // push the period to dependent zonegroups/zones | |
207 | encode(RGWRealmNotify::ZonesNeedPeriod, bl); | |
208 | encode(period, bl); | |
209 | // reload the gateway with the new period | |
210 | encode(RGWRealmNotify::Reload, bl); | |
211 | ||
212 | return notify_zone(dpp, bl, y); | |
213 | } | |
214 | ||
215 | ||
216 | int RGWRealm::find_zone(const DoutPrefixProvider *dpp, | |
217 | const rgw_zone_id& zid, | |
218 | RGWPeriod *pperiod, | |
219 | RGWZoneGroup *pzonegroup, | |
220 | bool *pfound, | |
221 | optional_yield y) const | |
222 | { | |
223 | auto& found = *pfound; | |
224 | ||
225 | found = false; | |
226 | ||
227 | string period_id; | |
228 | epoch_t epoch = 0; | |
229 | ||
230 | RGWPeriod period(period_id, epoch); | |
231 | int r = period.init(dpp, cct, sysobj_svc, get_id(), y, get_name()); | |
232 | if (r < 0) { | |
233 | ldpp_dout(dpp, 0) << "WARNING: period init failed: " << cpp_strerror(-r) << " ... skipping" << dendl; | |
234 | return r; | |
235 | } | |
236 | ||
237 | found = period.find_zone(dpp, zid, pzonegroup, y); | |
238 | if (found) { | |
239 | *pperiod = period; | |
240 | } | |
241 | return 0; | |
242 | } | |
243 | ||
244 | void RGWRealm::generate_test_instances(list<RGWRealm*> &o) | |
245 | { | |
246 | RGWRealm *z = new RGWRealm; | |
247 | o.push_back(z); | |
248 | o.push_back(new RGWRealm); | |
249 | } | |
250 | ||
251 | void RGWRealm::dump(Formatter *f) const | |
252 | { | |
253 | RGWSystemMetaObj::dump(f); | |
254 | encode_json("current_period", current_period, f); | |
255 | encode_json("epoch", epoch, f); | |
256 | } | |
257 | ||
258 | ||
259 | void RGWRealm::decode_json(JSONObj *obj) | |
260 | { | |
261 | RGWSystemMetaObj::decode_json(obj); | |
262 | JSONDecoder::decode_json("current_period", current_period, obj); | |
263 | JSONDecoder::decode_json("epoch", epoch, obj); | |
264 | } | |
265 |