From b7a9f21762e179fbc32b15f60ba659d6730ba535 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 28 Jun 2018 17:23:11 -0700 Subject: [PATCH] rgw: new utility crs - get user info - create bucket Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_cr_tools.cc | 140 ++++++++++++++++++++++++++++++++++++++++ src/rgw/rgw_cr_tools.h | 20 ++++++ src/rgw/rgw_op.cc | 22 +++---- src/rgw/rgw_op.h | 5 ++ 4 files changed, 176 insertions(+), 11 deletions(-) diff --git a/src/rgw/rgw_cr_tools.cc b/src/rgw/rgw_cr_tools.cc index ee9b9e13764..6176cc4df55 100644 --- a/src/rgw/rgw_cr_tools.cc +++ b/src/rgw/rgw_cr_tools.cc @@ -1,5 +1,11 @@ #include "rgw_cr_tools.h" +#include "rgw_bucket.h" #include "rgw_user.h" +#include "rgw_op.h" +#include "rgw_acl_s3.h" + +#define dout_context g_ceph_context +#define dout_subsys ceph_subsys_rgw template<> int RGWUserCreateCR::Request::_send_request() @@ -77,3 +83,137 @@ int RGWUserCreateCR::Request::_send_request() return RGWUserAdminOp_User::create(store, op_state, flusher); } +template<> +int RGWGetUserInfoCR::Request::_send_request() +{ + rgw_user user(params.tenant, params.uid); + return rgw_get_user_info_by_uid(store, user, result->user_info); +} + +template<> +int RGWBucketCreateLocalCR::Request::_send_request() +{ + CephContext *cct = store->ctx(); + + const auto& user_info = params.user_info.get(); + const auto& user = user_info->user_id; + const auto& bucket_name = params.bucket_name; + auto& placement_rule = params.placement_rule; + + const auto& zonegroup = store->get_zonegroup(); + + if (!placement_rule.empty() && + !zonegroup.placement_targets.count(placement_rule)) { + ldout(cct, 0) << "placement target (" << placement_rule << ")" + << " doesn't exist in the placement targets of zonegroup" + << " (" << store->get_zonegroup().api_name << ")" << dendl; + return -ERR_INVALID_LOCATION_CONSTRAINT; + } + + /* we need to make sure we read bucket info, it's not read before for this + * specific request */ + RGWObjectCtx obj_ctx(store); + RGWBucketInfo bucket_info; + map bucket_attrs; + + int ret = store->get_bucket_info(obj_ctx, user.tenant, bucket_name, + bucket_info, nullptr, &bucket_attrs); + if (ret < 0 && ret != -ENOENT) + return ret; + bool bucket_exists = (ret != -ENOENT); + + RGWAccessControlPolicy old_policy(cct); + ACLOwner bucket_owner; + bucket_owner.set_id(user); + bucket_owner.set_name(user_info->display_name); + if (bucket_exists) { + ret = rgw_op_get_bucket_policy_from_attr(cct, store, bucket_info, + bucket_attrs, &old_policy); + if (ret >= 0) { + if (old_policy.get_owner().get_id().compare(user) != 0) { + return -EEXIST; + } + } + } + + RGWBucketInfo master_info; + rgw_bucket *pmaster_bucket = nullptr; + uint32_t *pmaster_num_shards = nullptr; + real_time creation_time; + + string zonegroup_id = store->get_zonegroup().get_id(); + + if (bucket_exists) { + string selected_placement_rule; + rgw_bucket bucket; + bucket.tenant = user.tenant; + bucket.name = bucket_name; + ret = store->select_bucket_placement(*user_info, zonegroup_id, + placement_rule, + &selected_placement_rule, nullptr); + if (selected_placement_rule != bucket_info.placement_rule) { + ldout(cct, 0) << "bucket already exists on a different placement rule: " + << " selected_rule= " << selected_placement_rule + << " existing_rule= " << bucket_info.placement_rule << dendl; + return -EEXIST; + } + } + + /* Encode special metadata first as we're using std::map::emplace under + * the hood. This method will add the new items only if the map doesn't + * contain such keys yet. */ + RGWAccessControlPolicy_S3 policy(cct); + policy.create_canned(bucket_owner, bucket_owner, string()); /* default private policy */ + bufferlist aclbl; + policy.encode(aclbl); + map attrs; + attrs.emplace(std::move(RGW_ATTR_ACL), std::move(aclbl)); + + RGWQuotaInfo quota_info; + const RGWQuotaInfo * pquota_info = nullptr; + + rgw_bucket bucket; + bucket.tenant = user.tenant; + bucket.name = bucket_name; + + RGWBucketInfo info; + obj_version ep_objv; + + ret = store->create_bucket(*user_info, bucket, zonegroup_id, + placement_rule, bucket_info.swift_ver_location, + pquota_info, attrs, + info, nullptr, &ep_objv, creation_time, + pmaster_bucket, pmaster_num_shards, true); + + + if (ret && ret != -EEXIST) + return ret; + + bool existed = (ret == -EEXIST); + + if (existed) { + if (info.owner != user) { + ldout(cct, 20) << "NOTICE: bucket already exists under a different user (bucket=" << bucket << " user=" << user << " bucket_owner=" << info.owner << dendl; + return -EEXIST; + } + bucket = info.bucket; + } + + ret = rgw_link_bucket(store, user, bucket, + info.creation_time, false); + if (ret && !existed && ret != -EEXIST) { + /* if it exists (or previously existed), don't remove it! */ + int r = rgw_unlink_bucket(store, user, bucket.tenant, bucket.name); + if (r < 0) { + ldout(cct, 0) << "WARNING: failed to unlink bucket: ret=" << r << dendl; + } + } else if (ret == -EEXIST || (ret == 0 && existed)) { + ret = -ERR_BUCKET_EXISTS; + } + + if (ret < 0) { + ldout(cct, 0) << "ERROR: bucket creation (bucket=" << bucket << ") return ret=" << ret << dendl; + } + + return ret; +} diff --git a/src/rgw/rgw_cr_tools.h b/src/rgw/rgw_cr_tools.h index 9cd0b01cf76..8ac66263628 100644 --- a/src/rgw/rgw_cr_tools.h +++ b/src/rgw/rgw_cr_tools.h @@ -25,5 +25,25 @@ struct rgw_user_create_params { using RGWUserCreateCR = RGWSimpleWriteOnlyAsyncCR; +struct rgw_get_user_info_params { + std::string uid; + std::string tenant; +}; + +struct rgw_get_user_info_result { + RGWUserInfo user_info; +}; + +using RGWGetUserInfoCR = RGWSimpleAsyncCR; + +struct rgw_bucket_create_local_params { + shared_ptr user_info; + std::string bucket_name; + std::string placement_rule; +}; + +using RGWBucketCreateLocalCR = RGWSimpleWriteOnlyAsyncCR; + + #endif diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 2f8044981fb..f17be228b80 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -267,11 +267,11 @@ static int get_obj_policy_from_attr(CephContext *cct, * object: name of the object to get the ACL for. * Returns: 0 on success, -ERR# otherwise. */ -static int get_bucket_policy_from_attr(CephContext *cct, - RGWRados *store, - RGWBucketInfo& bucket_info, - map& bucket_attrs, - RGWAccessControlPolicy *policy) +int rgw_op_get_bucket_policy_from_attr(CephContext *cct, + RGWRados *store, + RGWBucketInfo& bucket_info, + map& bucket_attrs, + RGWAccessControlPolicy *policy) { return get_bucket_instance_policy_from_attr(cct, store, bucket_info, bucket_attrs, policy); } @@ -350,7 +350,7 @@ static int read_bucket_policy(RGWRados *store, return 0; } - int ret = get_bucket_policy_from_attr(s->cct, store, bucket_info, bucket_attrs, policy); + int ret = rgw_op_get_bucket_policy_from_attr(s->cct, store, bucket_info, bucket_attrs, policy); if (ret == -ENOENT) { ret = -ERR_NO_SUCH_BUCKET; } @@ -395,7 +395,7 @@ static int read_obj_policy(RGWRados *store, /* object does not exist checking the bucket's ACL to make sure that we send a proper error code */ RGWAccessControlPolicy bucket_policy(s->cct); - ret = get_bucket_policy_from_attr(s->cct, store, bucket_info, bucket_attrs, &bucket_policy); + ret = rgw_op_get_bucket_policy_from_attr(s->cct, store, bucket_info, bucket_attrs, &bucket_policy); if (ret < 0) { return ret; } @@ -2831,8 +2831,8 @@ void RGWCreateBucket::execute() s->bucket_owner.set_id(s->user->user_id); s->bucket_owner.set_name(s->user->display_name); if (s->bucket_exists) { - int r = get_bucket_policy_from_attr(s->cct, store, s->bucket_info, - s->bucket_attrs, &old_policy); + int r = rgw_op_get_bucket_policy_from_attr(s->cct, store, s->bucket_info, + s->bucket_attrs, &old_policy); if (r >= 0) { if (old_policy.get_owner().get_id().compare(s->user->user_id) != 0) { op_ret = -EEXIST; @@ -6362,8 +6362,8 @@ int RGWBulkUploadOp::handle_dir(const boost::string_ref path) if (bucket_exists) { RGWAccessControlPolicy old_policy(s->cct); - int r = get_bucket_policy_from_attr(s->cct, store, binfo, - battrs, &old_policy); + int r = rgw_op_get_bucket_policy_from_attr(s->cct, store, binfo, + battrs, &old_policy); if (r >= 0) { if (old_policy.get_owner().get_id().compare(s->user->user_id) != 0) { op_ret = -EEXIST; diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index e7f4225de13..dec114b90de 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -65,6 +65,11 @@ class StrategyRegistry; } } +int rgw_op_get_bucket_policy_from_attr(CephContext *cct, + RGWRados *store, + RGWBucketInfo& bucket_info, + map& bucket_attrs, + RGWAccessControlPolicy *policy); class RGWHandler { protected: -- 2.39.5