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