diff --git a/src/Makefile.am b/src/Makefile.am index edf0776a3be..250433fc81f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -393,7 +393,8 @@ librgw_a_SOURCES = \ rgw/rgw_multi_del.cc \ rgw/rgw_env.cc \ rgw/rgw_cors.cc \ - rgw/rgw_cors_s3.cc + rgw/rgw_cors_s3.cc \ + rgw/rgw_metadata.cc librgw_a_CFLAGS = ${CRYPTO_CFLAGS} ${AM_CFLAGS} librgw_a_CXXFLAGS = -Woverloaded-virtual ${AM_CXXFLAGS} noinst_LIBRARIES += librgw.a @@ -577,7 +578,8 @@ libcls_refcount_client_a_SOURCES = \ noinst_LIBRARIES += libcls_refcount_client.a libcls_version_client_a_SOURCES = \ - cls/version/cls_version_client.cc + cls/version/cls_version_client.cc \ + cls/version/cls_version_types.cc noinst_LIBRARIES += libcls_version_client.a libcls_rgw_client_a_SOURCES = \ @@ -2029,6 +2031,7 @@ noinst_HEADERS = \ rgw/rgw_multi.h\ rgw/rgw_policy_s3.h\ rgw/rgw_gc.h\ + rgw/rgw_metadata.h\ rgw/rgw_multi_del.h\ rgw/rgw_op.h\ rgw/rgw_http_client.h\ diff --git a/src/cls/version/cls_version_types.cc b/src/cls/version/cls_version_types.cc new file mode 100644 index 00000000000..2ed69733653 --- /dev/null +++ b/src/cls/version/cls_version_types.cc @@ -0,0 +1,11 @@ + +#include "cls/version/cls_version_types.h" +#include "common/Formatter.h" + + +void obj_version::dump(Formatter *f) const +{ + f->dump_int("ver", ver); + f->dump_string("tag", tag); +} + diff --git a/src/cls/version/cls_version_types.h b/src/cls/version/cls_version_types.h index 759ac25e298..82f37c00081 100644 --- a/src/cls/version/cls_version_types.h +++ b/src/cls/version/cls_version_types.h @@ -37,6 +37,8 @@ struct obj_version { return (ver == v->ver && tag.compare(v->tag) == 0); } + + void dump(Formatter *f) const; }; WRITE_CLASS_ENCODER(obj_version) diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 9756187e4e7..76fbe792b30 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -84,6 +84,7 @@ void _usage() cerr << " specified date (and optional time)\n"; cerr << " gc list dump expired garbage collection objects\n"; cerr << " gc process manually process garbage\n"; + cerr << " metadata get get metadata info\n"; cerr << "options:\n"; cerr << " --uid= user id\n"; cerr << " --subuser= subuser name\n"; @@ -185,6 +186,7 @@ enum { OPT_ZONE_LIST, OPT_CAPS_ADD, OPT_CAPS_RM, + OPT_METADATA_GET, }; static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more) @@ -207,7 +209,11 @@ static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more) strcmp(cmd, "regions") == 0 || strcmp(cmd, "region-map") == 0 || strcmp(cmd, "regionmap") == 0 || - strcmp(cmd, "zone") == 0) { + strcmp(cmd, "zone") == 0 || + strcmp(cmd, "temp") == 0 || + strcmp(cmd, "usage") == 0 || + strcmp(cmd, "user") == 0 || + strcmp(cmd, "metadata") == 0) { *need_more = true; return 0; } @@ -331,6 +337,9 @@ static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more) return OPT_GC_LIST; if (strcmp(cmd, "process") == 0) return OPT_GC_PROCESS; + } else if (strcmp(prev_cmd, "metadata") == 0) { + if (strcmp(cmd, "get") == 0) + return OPT_METADATA_GET; } return -EINVAL; @@ -529,9 +538,10 @@ int main(int argc, char **argv) map categories; string caps; int check_objects = false; - std::string infile; RGWUserAdminOpState user_op; RGWBucketAdminOpState bucket_op; + string infile; + string metadata_key; std::string val; std::ostringstream errs; @@ -633,6 +643,8 @@ int main(int argc, char **argv) caps = val; } else if (ceph_argparse_witharg(args, i, &val, "-i", "--infile", (char*)NULL)) { infile = val; + } else if (ceph_argparse_witharg(args, i, &val, "--metadata-key", (char*)NULL)) { + metadata_key = val; } else { ++i; } @@ -692,6 +704,8 @@ int main(int argc, char **argv) return 5; //EIO } + rgw_user_init(store->meta_mgr); + StoreDestructor store_destructor(store); if (raw_storage_op) { @@ -1436,5 +1450,15 @@ next: check_bad_user_bucket_mapping(store, user_id, fix); } + if (opt_cmd == OPT_METADATA_GET) { + int ret = store->meta_mgr->get(metadata_key, formatter); + if (ret < 0) { + cerr << "ERROR: can't get key: " << cpp_strerror(-ret) << std::endl; + return -ret; + } + + formatter->flush(cout); + } + return 0; } diff --git a/src/rgw/rgw_metadata.cc b/src/rgw/rgw_metadata.cc new file mode 100644 index 00000000000..dbc1f269a13 --- /dev/null +++ b/src/rgw/rgw_metadata.cc @@ -0,0 +1,81 @@ + + +#include "rgw_metadata.h" + + + +RGWMetadataManager::~RGWMetadataManager() +{ + map::iterator iter; + + for (iter = handlers.begin(); iter != handlers.end(); ++iter) { + delete iter->second; + } + + handlers.clear(); +} + +int RGWMetadataManager::register_handler(RGWMetadataHandler *handler) +{ + string type = handler->get_type(); + + if (handlers.find(type) != handlers.end()) + return -EINVAL; + + handlers[type] = handler; + + return 0; +} + +void RGWMetadataManager::parse_metadata_key(const string& metadata_key, string& type, string& entry) +{ + int pos = metadata_key.find(':'); + if (pos < 0) { + type = metadata_key; + } + + type = metadata_key.substr(0, pos); + entry = metadata_key.substr(pos + 1); +} + +int RGWMetadataManager::find_handler(const string& metadata_key, RGWMetadataHandler **handler, string& entry) +{ + string type; + + parse_metadata_key(metadata_key, type, entry); + + map::iterator iter = handlers.find(type); + if (iter == handlers.end()) + return -ENOENT; + + *handler = iter->second; + + return 0; + +} + +int RGWMetadataManager::get(string& metadata_key, Formatter *f) +{ + RGWMetadataHandler *handler; + string entry; + + int ret = find_handler(metadata_key, &handler, entry); + if (ret < 0) + return ret; + + return handler->get(store, metadata_key, entry, f); +} + +int RGWMetadataManager::update(string& metadata_key, bufferlist& bl) +{ + RGWMetadataHandler *handler; + string entry; + + int ret = find_handler(metadata_key, &handler, entry); + if (ret < 0) + return ret; + + return handler->update(store, entry, bl); +} + + diff --git a/src/rgw/rgw_metadata.h b/src/rgw/rgw_metadata.h new file mode 100644 index 00000000000..47518065fff --- /dev/null +++ b/src/rgw/rgw_metadata.h @@ -0,0 +1,40 @@ +#ifndef CEPH_RGW_METADATA_H +#define CEPH_RGW_METADATA_H + +#include + +#include "include/types.h" +#include "rgw_common.h" + +class RGWRados; + + +class RGWMetadataHandler { +public: + virtual ~RGWMetadataHandler() {} + virtual string get_type() = 0; + + virtual int get(RGWRados *store, string& key, string& entry, Formatter *f) = 0; + virtual int update(RGWRados *store, string& entry, bufferlist& bl) = 0; +}; + + +class RGWMetadataManager { + map handlers; + RGWRados *store; + + void parse_metadata_key(const string& metadata_key, string& type, string& entry); + + int find_handler(const string& metadata_key, RGWMetadataHandler **handler, string& entry); + +public: + RGWMetadataManager(RGWRados *_store) : store(_store) {} + ~RGWMetadataManager(); + + int register_handler(RGWMetadataHandler *handler); + + int get(string& metadata_key, Formatter *f); + int update(string& metadata_key, bufferlist& bl); +}; + +#endif diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index e83bc18c82f..5850c7276db 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -11,6 +11,7 @@ #include "rgw_rados.h" #include "rgw_cache.h" #include "rgw_acl.h" +#include "rgw_metadata.h" #include "cls/rgw/cls_rgw_types.h" #include "cls/rgw/cls_rgw_client.h" @@ -467,6 +468,7 @@ void RGWRadosCtx::set_prefetch_data(rgw_obj& obj) { void RGWRados::finalize() { + delete meta_mgr; if (use_gc_thread) { gc->stop_processor(); delete gc; @@ -540,6 +542,8 @@ int RGWRados::initialize() { int ret; + meta_mgr = new RGWMetadataManager(this); + ret = init_rados(); if (ret < 0) return ret; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 7798d97505d..a792cb4d788 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -8,6 +8,7 @@ #include "cls/rgw/cls_rgw_types.h" #include "cls/version/cls_version_types.h" #include "rgw_log.h" +#include "rgw_metadata.h" class RGWWatcher; class SafeTimer; @@ -528,7 +529,7 @@ public: num_watchers(0), watchers(NULL), watch_handles(NULL), bucket_id_lock("rados_bucket_id"), max_bucket_id(0), cct(NULL), rados(NULL), - pools_initialized(false) {} + pools_initialized(false), meta_mgr(NULL) {} void set_context(CephContext *_cct) { cct = _cct; @@ -545,6 +546,8 @@ public: RGWRegion region; RGWZoneParams zone; + RGWMetadataManager *meta_mgr; + virtual ~RGWRados() { if (rados) { rados->shutdown(); diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index fa19351882a..6973586a60d 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -4,6 +4,8 @@ #include #include "common/errno.h" +#include "common/Formatter.h" +#include "common/ceph_json.h" #include "rgw_rados.h" #include "rgw_acl.h" @@ -148,15 +150,15 @@ int rgw_get_user_info_from_index(RGWRados *store, string& key, rgw_bucket& bucke } /** - * Given an email, finds the user info associated with it. + * Given a uid, finds the user info associated with it. * returns: 0 on success, -ERR# on failure (including nonexistence) */ -int rgw_get_user_info_by_uid(RGWRados *store, string& uid, RGWUserInfo& info) +static int rgw_read_uid_info(RGWRados *store, string& uid, RGWUserInfo& info, obj_version *objv) { bufferlist bl; RGWUID user_id; - int ret = rgw_get_system_obj(store, NULL, store->zone.user_uid_pool, uid, bl, NULL); + int ret = rgw_get_system_obj(store, NULL, store->zone.user_uid_pool, uid, bl, objv); if (ret < 0) return ret; @@ -178,6 +180,11 @@ int rgw_get_user_info_by_uid(RGWRados *store, string& uid, RGWUserInfo& info) return 0; } +int rgw_get_user_info_by_uid(RGWRados *store, string& uid, RGWUserInfo& info) +{ + return rgw_read_uid_info(store, uid, info, NULL); +} + /** * Given an email, finds the user info associated with it. * returns: 0 on success, -ERR# on failure (including nonexistence) @@ -2184,6 +2191,7 @@ int RGWUserAdminOp_Caps::add(RGWRados *store, RGWUserAdminOpState& op_state, return 0; } + int RGWUserAdminOp_Caps::remove(RGWRados *store, RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher) { @@ -2210,3 +2218,34 @@ int RGWUserAdminOp_Caps::remove(RGWRados *store, RGWUserAdminOpState& op_state, return 0; } + +class RGWUserMetadataHandler : public RGWMetadataHandler { +public: + string get_type() { return "user"; } + int get(RGWRados *store, string& key, string& entry, Formatter *f) { + RGWUserInfo info; + + obj_version objv; + + int ret = rgw_read_uid_info(store, entry, info, &objv); + if (ret < 0) + return ret; + + f->open_object_section("metadata_info"); + encode_json("key", key, f); + encode_json("ver", objv, f); + encode_json("data", info, f); + f->close_section(); + f->flush(cout); + return 0; + } + + int update(RGWRados *store, string& metadata_key, bufferlist& bl) { + return 0; + } +}; + +void rgw_user_init(RGWMetadataManager *mm) +{ + mm->register_handler(new RGWUserMetadataHandler); +} diff --git a/src/rgw/rgw_user.h b/src/rgw/rgw_user.h index 3b277000b57..14a7c1d8cbd 100644 --- a/src/rgw/rgw_user.h +++ b/src/rgw/rgw_user.h @@ -616,4 +616,8 @@ public: RGWUserAdminOpState& op_state, RGWFormatterFlusher& flusher); }; +class RGWMetadataManager; + +extern void rgw_user_init(RGWMetadataManager *mm); + #endif