]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_cr_tools.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_cr_tools.cc
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 "common/errno.h"
5
6 #include "rgw_cr_tools.h"
7 #include "rgw_bucket.h"
8 #include "rgw_user.h"
9 #include "rgw_op.h"
10 #include "rgw_acl_s3.h"
11 #include "rgw_zone.h"
12
13 #include "services/svc_zone.h"
14
15 #define dout_context g_ceph_context
16 #define dout_subsys ceph_subsys_rgw
17
18 using namespace std;
19
20 template<>
21 int RGWUserCreateCR::Request::_send_request(const DoutPrefixProvider *dpp)
22 {
23 CephContext *cct = store->ctx();
24
25 const int32_t default_max_buckets =
26 cct->_conf.get_val<int64_t>("rgw_user_max_buckets");
27
28 RGWUserAdminOpState op_state(store);
29
30 auto& user = params.user;
31
32 op_state.set_user_id(user);
33 op_state.set_display_name(params.display_name);
34 op_state.set_user_email(params.email);
35 op_state.set_caps(params.caps);
36 op_state.set_access_key(params.access_key);
37 op_state.set_secret_key(params.secret_key);
38
39 if (!params.key_type.empty()) {
40 int32_t key_type = KEY_TYPE_S3;
41 if (params.key_type == "swift") {
42 key_type = KEY_TYPE_SWIFT;
43 }
44
45 op_state.set_key_type(key_type);
46 }
47
48 op_state.set_max_buckets(params.max_buckets.value_or(default_max_buckets));
49 op_state.set_suspension(params.suspended);
50 op_state.set_system(params.system);
51 op_state.set_exclusive(params.exclusive);
52
53 if (params.generate_key) {
54 op_state.set_generate_key();
55 }
56
57
58 if (params.apply_quota) {
59 RGWQuotaInfo bucket_quota;
60 RGWQuotaInfo user_quota;
61
62 if (cct->_conf->rgw_bucket_default_quota_max_objects >= 0) {
63 bucket_quota.max_objects = cct->_conf->rgw_bucket_default_quota_max_objects;
64 bucket_quota.enabled = true;
65 }
66
67 if (cct->_conf->rgw_bucket_default_quota_max_size >= 0) {
68 bucket_quota.max_size = cct->_conf->rgw_bucket_default_quota_max_size;
69 bucket_quota.enabled = true;
70 }
71
72 if (cct->_conf->rgw_user_default_quota_max_objects >= 0) {
73 user_quota.max_objects = cct->_conf->rgw_user_default_quota_max_objects;
74 user_quota.enabled = true;
75 }
76
77 if (cct->_conf->rgw_user_default_quota_max_size >= 0) {
78 user_quota.max_size = cct->_conf->rgw_user_default_quota_max_size;
79 user_quota.enabled = true;
80 }
81
82 if (bucket_quota.enabled) {
83 op_state.set_bucket_quota(bucket_quota);
84 }
85
86 if (user_quota.enabled) {
87 op_state.set_user_quota(user_quota);
88 }
89 }
90
91 RGWNullFlusher flusher;
92 return RGWUserAdminOp_User::create(dpp, store, op_state, flusher, null_yield);
93 }
94
95 template<>
96 int RGWGetUserInfoCR::Request::_send_request(const DoutPrefixProvider *dpp)
97 {
98 return store->ctl()->user->get_info_by_uid(dpp, params.user, result.get(), null_yield);
99 }
100
101 template<>
102 int RGWGetBucketInfoCR::Request::_send_request(const DoutPrefixProvider *dpp)
103 {
104 return store->get_bucket(dpp, nullptr, params.tenant, params.bucket_name, &result->bucket, null_yield);
105 }
106
107 template<>
108 int RGWBucketCreateLocalCR::Request::_send_request(const DoutPrefixProvider *dpp)
109 {
110 CephContext *cct = store->ctx();
111 auto& zone_svc = store->svc()->zone;
112
113 const auto& user_info = params.user_info.get();
114 const auto& user = user_info->user_id;
115 const auto& bucket_name = params.bucket_name;
116 auto& placement_rule = params.placement_rule;
117
118 if (!placement_rule.empty() &&
119 !zone_svc->get_zone_params().valid_placement(placement_rule)) {
120 ldpp_dout(dpp, 0) << "placement target (" << placement_rule << ")"
121 << " doesn't exist in the placement targets of zonegroup"
122 << " (" << zone_svc->get_zonegroup().api_name << ")" << dendl;
123 return -ERR_INVALID_LOCATION_CONSTRAINT;
124 }
125
126 /* we need to make sure we read bucket info, it's not read before for this
127 * specific request */
128 RGWBucketInfo bucket_info;
129 map<string, bufferlist> bucket_attrs;
130
131 int ret = store->getRados()->get_bucket_info(store->svc(), user.tenant, bucket_name,
132 bucket_info, nullptr, null_yield, dpp, &bucket_attrs);
133 if (ret < 0 && ret != -ENOENT)
134 return ret;
135 bool bucket_exists = (ret != -ENOENT);
136
137 RGWAccessControlPolicy old_policy(cct);
138 ACLOwner bucket_owner;
139 bucket_owner.set_id(user);
140 bucket_owner.set_name(user_info->display_name);
141 if (bucket_exists) {
142 ret = rgw_op_get_bucket_policy_from_attr(dpp, cct, store, bucket_info,
143 bucket_attrs, &old_policy, null_yield);
144 if (ret >= 0) {
145 if (old_policy.get_owner().get_id().compare(user) != 0) {
146 return -EEXIST;
147 }
148 }
149 }
150
151 RGWBucketInfo master_info;
152 rgw_bucket *pmaster_bucket = nullptr;
153 uint32_t *pmaster_num_shards = nullptr;
154 real_time creation_time;
155
156 string zonegroup_id = zone_svc->get_zonegroup().get_id();
157
158 if (bucket_exists) {
159 rgw_placement_rule selected_placement_rule;
160 rgw_bucket bucket;
161 bucket.tenant = user.tenant;
162 bucket.name = bucket_name;
163 ret = zone_svc->select_bucket_placement(dpp, *user_info, zonegroup_id,
164 placement_rule,
165 &selected_placement_rule, nullptr, null_yield);
166 if (selected_placement_rule != bucket_info.placement_rule) {
167 ldpp_dout(dpp, 0) << "bucket already exists on a different placement rule: "
168 << " selected_rule= " << selected_placement_rule
169 << " existing_rule= " << bucket_info.placement_rule << dendl;
170 return -EEXIST;
171 }
172 }
173
174 /* Encode special metadata first as we're using std::map::emplace under
175 * the hood. This method will add the new items only if the map doesn't
176 * contain such keys yet. */
177 RGWAccessControlPolicy_S3 policy(cct);
178 policy.create_canned(bucket_owner, bucket_owner, string()); /* default private policy */
179 bufferlist aclbl;
180 policy.encode(aclbl);
181 map<string, buffer::list> attrs;
182 attrs.emplace(std::move(RGW_ATTR_ACL), std::move(aclbl));
183
184 RGWQuotaInfo quota_info;
185 const RGWQuotaInfo * pquota_info = nullptr;
186
187 rgw_bucket bucket;
188 bucket.tenant = user.tenant;
189 bucket.name = bucket_name;
190
191 RGWBucketInfo info;
192 obj_version ep_objv;
193
194 ret = store->getRados()->create_bucket(*user_info, bucket, zonegroup_id,
195 placement_rule, bucket_info.swift_ver_location,
196 pquota_info, attrs,
197 info, nullptr, &ep_objv, creation_time,
198 pmaster_bucket, pmaster_num_shards, null_yield, dpp, true);
199
200
201 if (ret && ret != -EEXIST)
202 return ret;
203
204 bool existed = (ret == -EEXIST);
205
206 if (existed) {
207 if (info.owner != user) {
208 ldpp_dout(dpp, 20) << "NOTICE: bucket already exists under a different user (bucket=" << bucket << " user=" << user << " bucket_owner=" << info.owner << dendl;
209 return -EEXIST;
210 }
211 bucket = info.bucket;
212 }
213
214 ret = store->ctl()->bucket->link_bucket(user, bucket, info.creation_time, null_yield, dpp, false);
215 if (ret && !existed && ret != -EEXIST) {
216 /* if it exists (or previously existed), don't remove it! */
217 int r = store->ctl()->bucket->unlink_bucket(user, bucket, null_yield, dpp);
218 if (r < 0) {
219 ldpp_dout(dpp, 0) << "WARNING: failed to unlink bucket: ret=" << r << dendl;
220 }
221 } else if (ret == -EEXIST || (ret == 0 && existed)) {
222 ret = -ERR_BUCKET_EXISTS;
223 }
224
225 if (ret < 0) {
226 ldpp_dout(dpp, 0) << "ERROR: bucket creation (bucket=" << bucket << ") return ret=" << ret << dendl;
227 }
228
229 return ret;
230 }
231
232 template<>
233 int RGWObjectSimplePutCR::Request::_send_request(const DoutPrefixProvider *dpp)
234 {
235 RGWDataAccess::ObjectRef obj;
236
237 CephContext *cct = store->ctx();
238
239 int ret = params.bucket->get_object(params.key, &obj);
240 if (ret < 0) {
241 lderr(cct) << "ERROR: failed to get object: " << cpp_strerror(-ret) << dendl;
242 return -ret;
243 }
244
245 if (params.user_data) {
246 obj->set_user_data(*params.user_data);
247 }
248
249 ret = obj->put(params.data, params.attrs, dpp, null_yield);
250 if (ret < 0) {
251 ldpp_dout(dpp, -1) << "ERROR: put object returned error: " << cpp_strerror(-ret) << dendl;
252 }
253
254 return 0;
255 }
256
257 template<>
258 int RGWBucketLifecycleConfigCR::Request::_send_request(const DoutPrefixProvider *dpp)
259 {
260 CephContext *cct = store->ctx();
261
262 RGWLC *lc = store->getRados()->get_lc();
263 if (!lc) {
264 lderr(cct) << "ERROR: lifecycle object is not initialized!" << dendl;
265 return -EIO;
266 }
267
268 int ret = lc->set_bucket_config(params.bucket,
269 params.bucket_attrs,
270 &params.config);
271 if (ret < 0) {
272 lderr(cct) << "ERROR: failed to set lifecycle on bucke: " << cpp_strerror(-ret) << dendl;
273 return -ret;
274 }
275
276 return 0;
277 }
278
279 template<>
280 int RGWBucketGetSyncPolicyHandlerCR::Request::_send_request(const DoutPrefixProvider *dpp)
281 {
282 int r = store->ctl()->bucket->get_sync_policy_handler(params.zone,
283 params.bucket,
284 &result->policy_handler,
285 null_yield,
286 dpp);
287 if (r < 0) {
288 ldpp_dout(dpp, -1) << "ERROR: " << __func__ << "(): get_sync_policy_handler() returned " << r << dendl;
289 return r;
290 }
291
292 return 0;
293 }