]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_cr_tools.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_cr_tools.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 "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
9f95a23c
TL
13#include "services/svc_zone.h"
14
11fdf7f2
TL
15#define dout_context g_ceph_context
16#define dout_subsys ceph_subsys_rgw
17
20effc67
TL
18using namespace std;
19
11fdf7f2 20template<>
b3b6e05e 21int RGWUserCreateCR::Request::_send_request(const DoutPrefixProvider *dpp)
11fdf7f2
TL
22{
23 CephContext *cct = store->ctx();
24
f6b5b4d7
TL
25 const int32_t default_max_buckets =
26 cct->_conf.get_val<int64_t>("rgw_user_max_buckets");
11fdf7f2 27
20effc67 28 RGWUserAdminOpState op_state(store);
11fdf7f2
TL
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;
b3b6e05e 92 return RGWUserAdminOp_User::create(dpp, store, op_state, flusher, null_yield);
11fdf7f2
TL
93}
94
95template<>
b3b6e05e 96int RGWGetUserInfoCR::Request::_send_request(const DoutPrefixProvider *dpp)
11fdf7f2 97{
b3b6e05e 98 return store->ctl()->user->get_info_by_uid(dpp, params.user, result.get(), null_yield);
11fdf7f2
TL
99}
100
101template<>
b3b6e05e 102int RGWGetBucketInfoCR::Request::_send_request(const DoutPrefixProvider *dpp)
11fdf7f2 103{
20effc67 104 return store->get_bucket(dpp, nullptr, params.tenant, params.bucket_name, &result->bucket, null_yield);
11fdf7f2
TL
105}
106
107template<>
b3b6e05e 108int RGWBucketCreateLocalCR::Request::_send_request(const DoutPrefixProvider *dpp)
11fdf7f2
TL
109{
110 CephContext *cct = store->ctx();
9f95a23c 111 auto& zone_svc = store->svc()->zone;
11fdf7f2
TL
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)) {
b3b6e05e 120 ldpp_dout(dpp, 0) << "placement target (" << placement_rule << ")"
11fdf7f2
TL
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 */
11fdf7f2
TL
128 RGWBucketInfo bucket_info;
129 map<string, bufferlist> bucket_attrs;
130
9f95a23c 131 int ret = store->getRados()->get_bucket_info(store->svc(), user.tenant, bucket_name,
b3b6e05e 132 bucket_info, nullptr, null_yield, dpp, &bucket_attrs);
11fdf7f2
TL
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) {
b3b6e05e 142 ret = rgw_op_get_bucket_policy_from_attr(dpp, cct, store, bucket_info,
f67539c2 143 bucket_attrs, &old_policy, null_yield);
11fdf7f2
TL
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;
b3b6e05e 163 ret = zone_svc->select_bucket_placement(dpp, *user_info, zonegroup_id,
f67539c2
TL
164 placement_rule,
165 &selected_placement_rule, nullptr, null_yield);
11fdf7f2 166 if (selected_placement_rule != bucket_info.placement_rule) {
b3b6e05e 167 ldpp_dout(dpp, 0) << "bucket already exists on a different placement rule: "
11fdf7f2
TL
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
9f95a23c 194 ret = store->getRados()->create_bucket(*user_info, bucket, zonegroup_id,
11fdf7f2
TL
195 placement_rule, bucket_info.swift_ver_location,
196 pquota_info, attrs,
197 info, nullptr, &ep_objv, creation_time,
b3b6e05e 198 pmaster_bucket, pmaster_num_shards, null_yield, dpp, true);
11fdf7f2
TL
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) {
b3b6e05e 208 ldpp_dout(dpp, 20) << "NOTICE: bucket already exists under a different user (bucket=" << bucket << " user=" << user << " bucket_owner=" << info.owner << dendl;
11fdf7f2
TL
209 return -EEXIST;
210 }
211 bucket = info.bucket;
212 }
213
b3b6e05e 214 ret = store->ctl()->bucket->link_bucket(user, bucket, info.creation_time, null_yield, dpp, false);
11fdf7f2
TL
215 if (ret && !existed && ret != -EEXIST) {
216 /* if it exists (or previously existed), don't remove it! */
b3b6e05e 217 int r = store->ctl()->bucket->unlink_bucket(user, bucket, null_yield, dpp);
11fdf7f2 218 if (r < 0) {
b3b6e05e 219 ldpp_dout(dpp, 0) << "WARNING: failed to unlink bucket: ret=" << r << dendl;
11fdf7f2
TL
220 }
221 } else if (ret == -EEXIST || (ret == 0 && existed)) {
222 ret = -ERR_BUCKET_EXISTS;
223 }
224
225 if (ret < 0) {
b3b6e05e 226 ldpp_dout(dpp, 0) << "ERROR: bucket creation (bucket=" << bucket << ") return ret=" << ret << dendl;
11fdf7f2
TL
227 }
228
229 return ret;
230}
231
232template<>
b3b6e05e 233int RGWObjectSimplePutCR::Request::_send_request(const DoutPrefixProvider *dpp)
11fdf7f2
TL
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
9f95a23c 249 ret = obj->put(params.data, params.attrs, dpp, null_yield);
11fdf7f2 250 if (ret < 0) {
b3b6e05e 251 ldpp_dout(dpp, -1) << "ERROR: put object returned error: " << cpp_strerror(-ret) << dendl;
11fdf7f2
TL
252 }
253
254 return 0;
255}
256
257template<>
b3b6e05e 258int RGWBucketLifecycleConfigCR::Request::_send_request(const DoutPrefixProvider *dpp)
11fdf7f2
TL
259{
260 CephContext *cct = store->ctx();
261
9f95a23c 262 RGWLC *lc = store->getRados()->get_lc();
11fdf7f2
TL
263 if (!lc) {
264 lderr(cct) << "ERROR: lifecycle object is not initialized!" << dendl;
265 return -EIO;
266 }
267
20effc67 268 int ret = lc->set_bucket_config(params.bucket,
11fdf7f2
TL
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}
9f95a23c
TL
278
279template<>
b3b6e05e 280int RGWBucketGetSyncPolicyHandlerCR::Request::_send_request(const DoutPrefixProvider *dpp)
9f95a23c 281{
9f95a23c
TL
282 int r = store->ctl()->bucket->get_sync_policy_handler(params.zone,
283 params.bucket,
284 &result->policy_handler,
b3b6e05e
TL
285 null_yield,
286 dpp);
9f95a23c 287 if (r < 0) {
b3b6e05e 288 ldpp_dout(dpp, -1) << "ERROR: " << __func__ << "(): get_sync_policy_handler() returned " << r << dendl;
9f95a23c
TL
289 return r;
290 }
291
292 return 0;
293}