From 203d1f0ef3e0a958de4efb71441a38b7e3e78d1c Mon Sep 17 00:00:00 2001 From: Shilpa Jagannath Date: Thu, 11 Jul 2019 19:12:56 +0530 Subject: [PATCH] Create new user before deleting existing user. Migrate buckets one at a time. Signed-off-by: Shilpa Jagannath --- src/rgw/rgw_user.cc | 223 ++++++++++++++++++++++---------------------- 1 file changed, 110 insertions(+), 113 deletions(-) diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index b351073671751..b52e4f15145df 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -1938,63 +1938,23 @@ int RGWUser::check_op(RGWUserAdminOpState& op_state, std::string *err_msg) int RGWUser::execute_user_rename(RGWUserAdminOpState& op_state, std::string *err_msg) { - - // unlink buckets from existing user rgw_user& old_uid = op_state.get_user_id(); RGWUserInfo old_user_info = op_state.get_user_info(); - bool is_truncated = false; - string marker; - CephContext *cct = store->ctx(); - size_t max_buckets = cct->_conf->rgw_list_buckets_max_chunk; - vector read_buckets; - do { - RGWUserBuckets buckets; - int ret = rgw_read_user_buckets(store, old_uid, buckets, marker, string(), - max_buckets, false, &is_truncated); - if (ret < 0) { - set_err_msg(err_msg, "unable to read user bucket info"); - return ret; - } - - map& m = buckets.get_buckets(); - - std::map::iterator it; - for (it = m.begin(); it != m.end(); ++it) { - RGWBucketEnt obj = it->second; - read_buckets.push_back(obj.bucket); //Save the list of all buckets of the user to be able to use after bucket unlink - ret = rgw_unlink_bucket(store, old_uid, (obj.bucket.tenant), (obj.bucket.name)); - if (ret < 0) { - set_err_msg(err_msg, "error unlinking bucket " + cpp_strerror(-ret)); - return ret; - } - - marker = it->first; - } - - } while (is_truncated); - - // delete old user - std::string subprocess_msg; - int ret = execute_remove(op_state, &subprocess_msg); - if (ret < 0) { - set_err_msg(err_msg, "unable to remove existing user, " + subprocess_msg); - return ret; - } - - // create new user with old user's attributes rgw_user& uid = op_state.get_new_uid(); if (old_uid.tenant != uid.tenant) { set_err_msg(err_msg, "Users have to be under the same tenant namespace " - + old_uid.tenant + "!=" + uid.tenant); + + old_uid.tenant + "!=" + uid.tenant); + return -EINVAL; } string display_name = old_user_info.display_name; RGWUserAdminOpState new_op_state; new_op_state.set_user_id(uid); - ret = execute_rename(new_op_state, old_user_info, &subprocess_msg); + std::string subprocess_msg; + int ret = execute_rename(new_op_state, old_user_info, &subprocess_msg); if (ret < 0) { set_err_msg(err_msg, "unable to create new user, " + subprocess_msg); return ret; @@ -2007,93 +1967,130 @@ int RGWUser::execute_user_rename(RGWUserAdminOpState& op_state, std::string *err return ret; } - - // link bucket and objects to new user ACLOwner owner; RGWAccessControlPolicy policy_instance; - policy_instance.create_default(user_info.user_id, display_name); + policy_instance.create_default(uid, display_name); owner = policy_instance.get_owner(); bufferlist aclbl; policy_instance.encode(aclbl); - map attrs; - for (vector::iterator iter = read_buckets.begin(); iter != read_buckets.end(); ++iter) { - - RGWBucketInfo bucket_info; - rgw_bucket bucket = *iter; - RGWSysObjectCtx sys_ctx = store->svc.sysobj->init_obj_ctx(); + //unlink and link buckets to new user + bool is_truncated = false; + string marker; + string obj_marker; + CephContext *cct = store->ctx(); + size_t max_buckets = cct->_conf->rgw_list_buckets_max_chunk; - ret = store->get_bucket_info(sys_ctx, bucket.tenant, bucket.name, - bucket_info, NULL, null_yield, &attrs); + do { + RGWUserBuckets buckets; + int ret = rgw_read_user_buckets(store, old_uid, buckets, marker, string(), + max_buckets, false, &is_truncated); if (ret < 0) { - set_err_msg(err_msg, "failed to fetch bucket info for bucket= " + bucket.name); + set_err_msg(err_msg, "unable to read bucket info of user"); return ret; } - RGWObjVersionTracker objv_tracker; - RGWObjVersionTracker old_version = bucket_info.objv_tracker; + map attrs; + map& m = buckets.get_buckets(); + std::map::iterator it; - ret = store->set_bucket_owner(bucket, owner); - if (ret < 0) { - set_err_msg(err_msg, "failed to set bucket owner: " + cpp_strerror(-ret)); - return ret; - } + for (it = m.begin(); it != m.end(); ++it) { + RGWBucketEnt obj = it->second; + ret = rgw_unlink_bucket(store, old_uid, obj.bucket.tenant, obj.bucket.name); + if (ret < 0) { + set_err_msg(err_msg, "error unlinking bucket " + cpp_strerror(-ret)); + return ret; + } - const rgw_pool& root_pool = store->svc.zone->get_zone_params().domain_root; - std::string bucket_entry; - rgw_make_bucket_entry_name(bucket.tenant, bucket.name, bucket_entry); - rgw_raw_obj obj(root_pool, bucket_entry); - auto obj_ctx = store->svc.sysobj->init_obj_ctx(); - auto sysobj = obj_ctx.get_obj(obj); - rgw_raw_obj obj_bucket_instance; + marker = it->first; - store->get_bucket_instance_obj(bucket, obj_bucket_instance); - auto inst_sysobj = obj_ctx.get_obj(obj_bucket_instance); - ret = inst_sysobj.wop() - .set_objv_tracker(&objv_tracker) - .write_attr(RGW_ATTR_ACL, aclbl, null_yield); - if (ret < 0) { - set_err_msg(err_msg, "failed to set new acl on bucket " + bucket.name); - return ret; - } + RGWBucketInfo bucket_info; + RGWSysObjectCtx sys_ctx = store->svc.sysobj->init_obj_ctx(); + + ret = store->get_bucket_info(sys_ctx, obj.bucket.tenant, obj.bucket.name, + bucket_info, NULL, null_yield, &attrs); + if (ret < 0) { + set_err_msg(err_msg, "failed to fetch bucket info for bucket= " + obj.bucket.name); + return ret; + } - RGWBucketEntryPoint ep; - ep.bucket = bucket_info.bucket; - ep.owner = user_info.user_id; - ep.creation_time = bucket_info.creation_time; - ep.linked = true; - map ep_attrs; - rgw_ep_info ep_data{ep, ep_attrs}; + RGWObjVersionTracker objv_tracker; + RGWObjVersionTracker old_version = bucket_info.objv_tracker; - ret = rgw_link_bucket(store, user_info.user_id, bucket_info.bucket, - ceph::real_time(), true, &ep_data); - if (ret < 0) { - set_err_msg(err_msg, "failed to link bucket " + bucket.name + " to new user"); - return ret; - } + ret = store->set_bucket_owner(obj.bucket, owner); + if (ret < 0) { + set_err_msg(err_msg, "failed to set bucket owner: " + cpp_strerror(-ret)); + return ret; + } - RGWBucketInfo new_bucket_info; - ret = store->get_bucket_info(sys_ctx, bucket.tenant, bucket.name, - new_bucket_info, NULL, null_yield, &attrs); - if (ret < 0) { - set_err_msg(err_msg, "failed to fetch bucket info for bucket= " + bucket.name); - return ret; - } + const rgw_pool& root_pool = store->svc.zone->get_zone_params().domain_root; + std::string bucket_entry; + rgw_make_bucket_entry_name(obj.bucket.tenant, obj.bucket.name, bucket_entry); + rgw_raw_obj ob(root_pool, bucket_entry); + auto sysobj = sys_ctx.get_obj(ob); + rgw_raw_obj obj_bucket_instance; + + store->get_bucket_instance_obj(obj.bucket, obj_bucket_instance); + auto inst_sysobj = sys_ctx.get_obj(obj_bucket_instance); + ret = inst_sysobj.wop() + .set_objv_tracker(&objv_tracker) + .write_attr(RGW_ATTR_ACL, aclbl, null_yield); + if (ret < 0) { + set_err_msg(err_msg, "failed to set new acl on bucket " + obj.bucket.name); + return ret; + } - ret = rgw_bucket_chown(store, user_info, new_bucket_info, marker, attrs); - if (ret < 0) { - set_err_msg(err_msg, "failed to run bucket chown" + cpp_strerror(-ret)); - return ret; + RGWBucketEntryPoint ep; + ep.bucket = bucket_info.bucket; + ep.owner = uid; + ep.creation_time = bucket_info.creation_time; + ep.linked = true; + map ep_attrs; + rgw_ep_info ep_data{ep, ep_attrs}; + + ret = rgw_link_bucket(store, uid, bucket_info.bucket, + ceph::real_time(), true, &ep_data); + if (ret < 0) { + set_err_msg(err_msg, "failed to link bucket " + obj.bucket.name + " to new user"); + return ret; + } + + RGWBucketInfo new_bucket_info; + ret = store->get_bucket_info(sys_ctx, obj.bucket.tenant, obj.bucket.name, + new_bucket_info, NULL, null_yield, &attrs); + if (ret < 0) { + set_err_msg(err_msg, "failed to fetch bucket info for bucket= " + obj.bucket.name); + return ret; + } + + ret = rgw_bucket_chown(store, user_info, new_bucket_info, obj_marker, attrs); + if (ret < 0) { + set_err_msg(err_msg, "failed to run bucket chown" + cpp_strerror(-ret)); + return ret; + } } + + } while (is_truncated); + + // delete old user + ret = execute_remove(op_state, &subprocess_msg); + if (ret < 0) { + set_err_msg(err_msg, "unable to remove existing user, " + subprocess_msg); + return ret; } + + ret = update(new_op_state, err_msg); + if (ret < 0) + return ret; + return 0; } -int RGWUser:: execute_rename(RGWUserAdminOpState& op_state, RGWUserInfo& old_user_info, std::string *err_msg) +int RGWUser::execute_rename(RGWUserAdminOpState& op_state, RGWUserInfo& old_user_info, std::string *err_msg) { std::string subprocess_msg; int ret = 0; - bool defer_user_update = true; + bool defer_user_update = false; rgw_user& user_id = op_state.get_user_id(); @@ -2109,16 +2106,16 @@ int RGWUser:: execute_rename(RGWUserAdminOpState& op_state, RGWUserInfo& old_use for (it = modify_keys.begin(); it != modify_keys.end(); it++) { - RGWAccessKey old_key; - old_key = it->second; + RGWAccessKey old_key; + old_key = it->second; - std::string id; - user_id.to_str(id); - id.append(":"); - id.append(old_key.subuser); + std::string id; + user_id.to_str(id); + id.append(":"); + id.append(old_key.subuser); - old_key.id = id; - user_info.swift_keys[id] = old_key; + old_key.id = id; + user_info.swift_keys[id] = old_key; } op_state.set_user_info(user_info); -- 2.39.5