From: Marcus Watts Date: Tue, 21 Aug 2018 22:09:33 +0000 (-0400) Subject: rgw: bucket link: Add ability to name bucket w/ different tenant. X-Git-Tag: v15.1.0~1944^2~18 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=edc18a56d2fbc1c6b8e4e8ae950ab354c7df40f0;p=ceph.git rgw: bucket link: Add ability to name bucket w/ different tenant. This is not a complete fix; but it makes it possible for the bucket link command to correctly find and attempt to link a bucket to a user with a different tenant. The reason this is not a complete fix is that with just this change, the resulting bucket is "broken"; a duplicate endpoint but 0 length contents is created, and the info entry is not correctly moved. Fixes: http://tracker.ceph.com/issues/35885 Signed-off-by: Marcus Watts --- diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index c6db07186ff..2f18b5d5a62 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -781,15 +781,20 @@ static void set_err_msg(std::string *sink, std::string msg) *sink = msg; } -int RGWBucket::init(RGWRados *storage, RGWBucketAdminOpState& op_state) +int RGWBucket::init(RGWRados *storage, RGWBucketAdminOpState& op_state, + std::string *err_msg) { - if (!storage) + std::string bucket_tenant; + if (!storage) { + set_err_msg(err_msg, "no storage!"); return -EINVAL; + } store = storage; rgw_user user_id = op_state.get_user_id(); tenant = user_id.tenant; + bucket_tenant = tenant; bucket_name = op_state.get_bucket_name(); RGWUserBuckets user_buckets; auto obj_ctx = store->svc.sysobj->init_obj_ctx(); @@ -797,9 +802,18 @@ int RGWBucket::init(RGWRados *storage, RGWBucketAdminOpState& op_state) if (bucket_name.empty() && user_id.empty()) return -EINVAL; + // split possible tenant/name + auto pos = bucket_name.find('/'); + if (pos != boost::string_ref::npos) { + bucket_tenant = bucket_name.substr(0, pos); + bucket_name = bucket_name.substr(pos + 1); + } + if (!bucket_name.empty()) { int r = store->get_bucket_info(obj_ctx, tenant, bucket_name, bucket_info, NULL, null_yield); + if (r < 0) { + set_err_msg(err_msg, "failed to fetch bucket info for bucket=" + bucket_name); ldout(store->ctx(), 0) << "could not get bucket info for bucket=" << bucket_name << dendl; return r; } @@ -809,8 +823,10 @@ int RGWBucket::init(RGWRados *storage, RGWBucketAdminOpState& op_state) if (!user_id.empty()) { int r = rgw_get_user_info_by_uid(store, user_id, user_info); - if (r < 0) + if (r < 0) { + set_err_msg(err_msg, "failed to fetch user info"); return r; + } op_state.display_name = user_info.display_name; } @@ -827,13 +843,19 @@ int RGWBucket::link(RGWBucketAdminOpState& op_state, std::string *err_msg) } string bucket_id = op_state.get_bucket_id(); +#if 0 if (bucket_id.empty()) { set_err_msg(err_msg, "empty bucket instance id"); return -EINVAL; } +#endif std::string display_name = op_state.get_user_display_name(); rgw_bucket bucket = op_state.get_bucket(); + if (!bucket_id.empty() && bucket_id != bucket.bucket_id) { + set_err_msg(err_msg, "specified bucket id does not match"); + return -EINVAL; + } const rgw_pool& root_pool = store->svc.zone->get_zone_params().domain_root; std::string bucket_entry; @@ -847,6 +869,7 @@ int RGWBucket::link(RGWBucketAdminOpState& op_state, std::string *err_msg) auto obj_ctx = store->svc.sysobj->init_obj_ctx(); int r = store->get_bucket_instance_info(obj_ctx, bucket, bucket_info, NULL, &attrs, null_yield); if (r < 0) { + set_err_msg(err_msg, "failed to refetch bucket info"); return r; } @@ -892,6 +915,7 @@ int RGWBucket::link(RGWBucketAdminOpState& op_state, std::string *err_msg) .set_objv_tracker(&objv_tracker) .write_attr(RGW_ATTR_ACL, aclbl, null_yield); if (r < 0) { + set_err_msg(err_msg, "failed to set new acl"); return r; } @@ -907,12 +931,14 @@ int RGWBucket::link(RGWBucketAdminOpState& op_state, std::string *err_msg) .set_objv_tracker(&objv_tracker) .write_attr(RGW_ATTR_ACL, aclbl, null_yield); if (r < 0) { + set_err_msg(err_msg, "failed to set bucket policy"); return r; } r = rgw_link_bucket(store, user_info.user_id, bucket_info.bucket, ceph::real_time()); if (r < 0) { + set_err_msg(err_msg, "failed to relink bucket"); return r; } } @@ -1351,7 +1377,7 @@ int RGWBucketAdminOp::link(RGWRados *store, RGWBucketAdminOpState& op_state, str { RGWBucket bucket; - int ret = bucket.init(store, op_state); + int ret = bucket.init(store, op_state, err); if (ret < 0) return ret; diff --git a/src/rgw/rgw_bucket.h b/src/rgw/rgw_bucket.h index 3892a76e70f..086a4b6ebbd 100644 --- a/src/rgw/rgw_bucket.h +++ b/src/rgw/rgw_bucket.h @@ -316,7 +316,8 @@ class RGWBucket public: RGWBucket() : store(NULL), handle(NULL), failure(false) {} - int init(RGWRados *storage, RGWBucketAdminOpState& op_state); + int init(RGWRados *storage, RGWBucketAdminOpState& op_state, + std::string *err_msg = NULL); int check_bad_index_multipart(RGWBucketAdminOpState& op_state, RGWFormatterFlusher& flusher, std::string *err_msg = NULL); diff --git a/src/rgw/rgw_rest_bucket.cc b/src/rgw/rgw_rest_bucket.cc index b8a2c75502d..165f70126d7 100644 --- a/src/rgw/rgw_rest_bucket.cc +++ b/src/rgw/rgw_rest_bucket.cc @@ -131,17 +131,20 @@ void RGWOp_Bucket_Link::execute() std::string uid_str; std::string bucket; std::string bucket_id; + std::string new_bucket_name; RGWBucketAdminOpState op_state; RESTArgs::get_string(s, "uid", uid_str, &uid_str); RESTArgs::get_string(s, "bucket", bucket, &bucket); RESTArgs::get_string(s, "bucket-id", bucket_id, &bucket_id); + RESTArgs::get_string(s, "new-bucket-name", new_bucket_name, &new_bucket_name); rgw_user uid(uid_str); op_state.set_user_id(uid); op_state.set_bucket_name(bucket); op_state.set_bucket_id(bucket_id); + op_state.set_new_bucket_name(new_bucket_name); http_ret = RGWBucketAdminOp::link(store, op_state); }