From f74c08f155eaa545f8944b3b5836a30efce5ae7b Mon Sep 17 00:00:00 2001 From: songshuangyang Date: Tue, 13 Nov 2018 17:32:41 +0800 Subject: [PATCH] rgw: add list user admin OP API The radosgw-admin tool support the `user list` subcommand to list radosgw users, but there is no user listing function for the admin OP API. It needs to support this API. Signed-off-by: Oshyn Song (cherry picked from commit 97e1ff50e57a51744a6d864cef15f9afe0e84b66) Conflicts: src/rgw/rgw_user.h - needed to adapt the list_user RGWOp name() override --- src/rgw/rgw_common.cc | 1 + src/rgw/rgw_rest_user.cc | 31 ++++++++++++++++++ src/rgw/rgw_user.cc | 71 ++++++++++++++++++++++++++++++++++++++++ src/rgw/rgw_user.h | 12 +++++++ 4 files changed, 115 insertions(+) diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index c30b6af20bcfd..ac765f9cad851 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -942,6 +942,7 @@ void RGWHTTPArgs::append(const string& name, const string& val) (name.compare("index") == 0) || (name.compare("policy") == 0) || (name.compare("quota") == 0) || + (name.compare("list") == 0) || (name.compare("object") == 0)) { if (!admin_subresource_added) { diff --git a/src/rgw/rgw_rest_user.cc b/src/rgw/rgw_rest_user.cc index bd561d0c470cf..2eaeaeb66c41c 100644 --- a/src/rgw/rgw_rest_user.cc +++ b/src/rgw/rgw_rest_user.cc @@ -12,6 +12,34 @@ #define dout_subsys ceph_subsys_rgw +class RGWOp_User_List : public RGWRESTOp { + +public: + RGWOp_User_List() {} + + int check_caps(RGWUserCaps& caps) override { + return caps.check_cap("users", RGW_CAP_READ); + } + + void execute() override; + + const string name() override { return "list_user"; } +}; + +void RGWOp_User_List::execute() +{ + RGWUserAdminOpState op_state; + + uint32_t max_entries; + std::string marker; + RESTArgs::get_uint32(s, "max-entries", 1000, &max_entries); + RESTArgs::get_string(s, "marker", marker, &marker); + + op_state.max_entries = max_entries; + op_state.marker = marker; + http_ret = RGWUserAdminOp_User::list(store, op_state, flusher); +} + class RGWOp_User_Info : public RGWRESTOp { public: @@ -895,6 +923,9 @@ RGWOp *RGWHandler_User::op_get() if (s->info.args.sub_resource_exists("quota")) return new RGWOp_Quota_Info; + if (s->info.args.sub_resource_exists("list")) + return new RGWOp_User_List; + return new RGWOp_User_Info; } diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index ca0be35823080..39f0d7879c95b 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -2312,6 +2312,77 @@ int RGWUser::info(RGWUserInfo& fetched_info, std::string *err_msg) return 0; } +int RGWUser::list(RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher) +{ + Formatter *formatter = flusher.get_formatter(); + void *handle = nullptr; + std::string metadata_key = "user"; + if (op_state.max_entries > 1000) { + op_state.max_entries = 1000; + } + + int ret = store->meta_mgr->list_keys_init(metadata_key, op_state.marker, &handle); + if (ret < 0) { + return ret; + } + + bool truncated = false; + uint64_t count = 0; + uint64_t left = 0; + flusher.start(0); + + // open the result object section + formatter->open_object_section("result"); + + // open the user id list array section + formatter->open_array_section("keys"); + do { + std::list keys; + left = op_state.max_entries - count; + ret = store->meta_mgr->list_keys_next(handle, left, keys, &truncated); + if (ret < 0 && ret != -ENOENT) { + return ret; + } if (ret != -ENOENT) { + for (std::list::iterator iter = keys.begin(); iter != keys.end(); ++iter) { + formatter->dump_string("key", *iter); + ++count; + } + } + } while (truncated && left > 0); + // close user id list section + formatter->close_section(); + + formatter->dump_bool("truncated", truncated); + formatter->dump_int("count", count); + if (truncated) { + formatter->dump_string("marker", store->meta_mgr->get_marker(handle)); + } + + // close result object section + formatter->close_section(); + + store->meta_mgr->list_keys_complete(handle); + + flusher.flush(); + return 0; +} + +int RGWUserAdminOp_User::list(RGWRados *store, RGWUserAdminOpState& op_state, + RGWFormatterFlusher& flusher) +{ + RGWUser user; + + int ret = user.init_storage(store); + if (ret < 0) + return ret; + + ret = user.list(op_state, flusher); + if (ret < 0) + return ret; + + return 0; +} + int RGWUserAdminOp_User::info(RGWRados *store, RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher) { diff --git a/src/rgw/rgw_user.h b/src/rgw/rgw_user.h index c9bca868bd4e0..ae5816e010cda 100644 --- a/src/rgw/rgw_user.h +++ b/src/rgw/rgw_user.h @@ -226,6 +226,10 @@ struct RGWUserAdminOpState { RGWQuotaInfo bucket_quota; RGWQuotaInfo user_quota; + // req parameters for listing user + std::string marker; + uint32_t max_entries; + void set_access_key(std::string& access_key) { if (access_key.empty()) return; @@ -534,6 +538,8 @@ struct RGWUserAdminOpState { found_by_email = false; found_by_key = false; mfa_ids_specified = false; + max_entries = 1000; + marker = ""; } }; @@ -699,6 +705,9 @@ public: /* info from an already populated RGWUser */ int info (RGWUserInfo& fetched_info, std::string *err_msg = NULL); + /* list the existing users */ + int list(RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher); + friend class RGWAccessKeyPool; friend class RGWSubUserPool; friend class RGWUserCapPool; @@ -709,6 +718,9 @@ public: class RGWUserAdminOp_User { public: + static int list(RGWRados *store, + RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher); + static int info(RGWRados *store, RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher); -- 2.39.5