Config Reference <config-ref>
S3 API <s3>
Swift API <swift/index>
-
+ Admin API <admin/index>
+ troubleshooting
++
OPT_OBJECT_RM,
OPT_GC_LIST,
OPT_GC_PROCESS,
+ OPT_CLUSTER_INFO,
+ OPT_CAPS_ADD,
+ OPT_CAPS_RM,
};
static uint32_t str_to_perm(const char *str)
strcmp(cmd, "log") == 0 ||
strcmp(cmd, "usage") == 0 ||
strcmp(cmd, "object") == 0 ||
+ strcmp(cmd, "cluster") == 0 ||
strcmp(cmd, "temp") == 0 ||
+ strcmp(cmd, "caps") == 0 ||
strcmp(cmd, "gc") == 0) {
*need_more = true;
return 0;
KEY_TYPE_S3,
};
- static void parse_date(string& date, uint64_t *epoch, string *out_date = NULL, string *out_time = NULL)
- {
- struct tm tm;
-
- memset(&tm, 0, sizeof(tm));
-
- const char *p = strptime(date.c_str(), "%Y-%m-%d", &tm);
- if (p) {
- if (*p == ' ') {
- p++;
- strptime(p, " %H:%M:%S", &tm);
- }
- } else {
- return;
- }
- time_t t = timegm(&tm);
- if (epoch)
- *epoch = (uint64_t)t;
-
- if (out_date) {
- char buf[32];
- strftime(buf, sizeof(buf), "%F", &tm);
- *out_date = buf;
- }
- if (out_time) {
- char buf[32];
- strftime(buf, sizeof(buf), "%T", &tm);
- *out_time = buf;
- }
- }
-
-static int remove_object(rgw_bucket& bucket, std::string& object)
+static int remove_object(RGWRados *store, rgw_bucket& bucket, std::string& object)
{
int ret = -EINVAL;
- RGWRadosCtx *rctx = new RGWRadosCtx();
+ RGWRadosCtx *rctx = new RGWRadosCtx(store);
rgw_obj obj(bucket,object);
- ret = rgwstore->delete_obj(rctx, obj);
+ ret = store->delete_obj(rctx, obj);
return ret;
}
--static int remove_bucket(rgw_bucket& bucket, bool delete_children)
++static int remove_bucket(RGWRados *store, rgw_bucket& bucket, bool delete_children)
{
int ret;
map<RGWObjCategory, RGWBucketStats> stats;
int purge_keys = false;
int yes_i_really_mean_it = false;
int delete_child_objects = false;
+ int fix = false;
int max_buckets = -1;
map<string, bool> categories;
+ string caps;
std::string val;
std::ostringstream errs;
// do nothing
} else if (ceph_argparse_binary_flag(args, i, &yes_i_really_mean_it, NULL, "--yes-i-really-mean-it", (char*)NULL)) {
// do nothing
+ } else if (ceph_argparse_binary_flag(args, i, &fix, NULL, "--fix", (char*)NULL)) {
+ // do nothing
+ } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) {
+ caps = val;
} else {
++i;
}
user_modify_op = (opt_cmd == OPT_USER_MODIFY || opt_cmd == OPT_SUBUSER_MODIFY ||
opt_cmd == OPT_SUBUSER_CREATE || opt_cmd == OPT_SUBUSER_RM ||
- opt_cmd == OPT_KEY_CREATE || opt_cmd == OPT_KEY_RM || opt_cmd == OPT_USER_RM);
+ opt_cmd == OPT_KEY_CREATE || opt_cmd == OPT_KEY_RM || opt_cmd == OPT_USER_RM ||
+ opt_cmd == OPT_CAPS_ADD || opt_cmd == OPT_CAPS_RM);
- RGWStoreManager store_manager;
- store = store_manager.init(g_ceph_context, false);
+ store = RGWStoreManager::get_storage(g_ceph_context, false);
if (!store) {
cerr << "couldn't init storage provider" << std::endl;
return 5; //EIO
if (m.size() > 0 && purge_data) {
for (std::map<string, RGWBucketEnt>::iterator it = m.begin(); it != m.end(); it++) {
-- ret = remove_bucket(((*it).second).bucket, true);
++ ret = remove_bucket(store, ((*it).second).bucket, true);
if (ret < 0)
return ret;
uint64_t start_epoch = 0;
uint64_t end_epoch = (uint64_t)-1;
- parse_date(start_date, &start_epoch);
- parse_date(end_date, &end_epoch);
-
- uint32_t max_entries = 1000;
-
- bool is_truncated = true;
-
- RGWUsageIter usage_iter;
-
- map<rgw_user_bucket, rgw_usage_log_entry> usage;
-
- formatter->open_object_section("usage");
- if (show_log_entries) {
- formatter->open_array_section("entries");
- }
- string last_owner;
- bool user_section_open = false;
- map<string, rgw_usage_log_entry> summary_map;
- while (is_truncated) {
- int ret = store->read_usage(user_id, start_epoch, end_epoch, max_entries,
- &is_truncated, usage_iter, usage);
-
- if (ret == -ENOENT) {
- ret = 0;
- is_truncated = false;
- }
-
- if (ret < 0) {
- cerr << "ERROR: read_usage() returned ret=" << ret << std::endl;
- break;
- }
-
- map<rgw_user_bucket, rgw_usage_log_entry>::iterator iter;
- for (iter = usage.begin(); iter != usage.end(); ++iter) {
- const rgw_user_bucket& ub = iter->first;
- const rgw_usage_log_entry& entry = iter->second;
-
- if (show_log_entries) {
- if (ub.user.compare(last_owner) != 0) {
- if (user_section_open) {
- formatter->close_section();
- formatter->close_section();
- }
- formatter->open_object_section("user");
- formatter->dump_string("owner", ub.user);
- formatter->open_array_section("buckets");
- user_section_open = true;
- last_owner = ub.user;
- }
- formatter->open_object_section("bucket");
- formatter->dump_string("bucket", ub.bucket);
- utime_t ut(entry.epoch, 0);
- ut.gmtime(formatter->dump_stream("time"));
- formatter->dump_int("epoch", entry.epoch);
- dump_usage_categories_info(formatter, entry, categories);
- formatter->close_section(); // bucket
- formatter->flush(cout);
- }
-
- summary_map[ub.user].aggregate(entry, &categories);
- }
+ int ret = parse_date(start_date, &start_epoch);
+ if (ret < 0) {
+ cerr << "ERROR: failed to parse start date" << std::endl;
+ return 1;
}
- if (show_log_entries) {
- if (user_section_open) {
- formatter->close_section(); // buckets
- formatter->close_section(); //user
- }
- formatter->close_section(); // entries
+ ret = parse_date(end_date, &end_epoch);
+ if (ret < 0) {
+ cerr << "ERROR: failed to parse end date" << std::endl;
+ return 1;
}
- if (show_log_sum) {
- formatter->open_array_section("summary");
- map<string, rgw_usage_log_entry>::iterator siter;
- for (siter = summary_map.begin(); siter != summary_map.end(); ++siter) {
- const rgw_usage_log_entry& entry = siter->second;
- formatter->open_object_section("user");
- formatter->dump_string("user", siter->first);
- dump_usage_categories_info(formatter, entry, categories);
- rgw_usage_data total_usage;
- entry.sum(total_usage, categories);
- formatter->open_object_section("total");
- formatter->dump_int("bytes_sent", total_usage.bytes_sent);
- formatter->dump_int("bytes_received", total_usage.bytes_received);
- formatter->dump_int("ops", total_usage.ops);
- formatter->dump_int("successful_ops", total_usage.successful_ops);
- formatter->close_section(); // total
-
- formatter->close_section(); // user
-
- formatter->flush(cout);
- }
+ RGWStreamFlusher f(formatter, cout);
- formatter->close_section(); // summary
- ret = RGWUsage::show(rgwstore, user_id, start_epoch, end_epoch,
- show_log_entries, show_log_sum, &categories,
- f);
++ ret = RGWUsage::show(store, user_id, start_epoch, end_epoch,
++ show_log_entries, show_log_sum, &categories,
++ f);
+ if (ret < 0) {
+ cerr << "ERROR: failed to show usage" << std::endl;
+ return 1;
}
-
- formatter->close_section(); // usage
- formatter->flush(cout);
}
if (opt_cmd == OPT_USAGE_TRIM) {
uint64_t start_epoch = 0;
uint64_t end_epoch = (uint64_t)-1;
- parse_date(start_date, &start_epoch);
- parse_date(end_date, &end_epoch);
+ int ret = parse_date(start_date, &start_epoch);
+ if (ret < 0) {
+ cerr << "ERROR: failed to parse start date" << std::endl;
+ return 1;
+ }
+ ret = parse_date(end_date, &end_epoch);
+ if (ret < 0) {
+ cerr << "ERROR: failed to parse end date" << std::endl;
+ return 1;
+ }
- int ret = store->trim_usage(user_id, start_epoch, end_epoch);
- ret = RGWUsage::trim(rgwstore, user_id, start_epoch, end_epoch);
++ ret = RGWUsage::trim(store, user_id, start_epoch, end_epoch);
if (ret < 0) {
cerr << "ERROR: read_usage() returned ret=" << ret << std::endl;
return 1;
}
}
+ if (opt_cmd == OPT_BUCKET_CHECK) {
+ map<RGWObjCategory, RGWBucketStats> existing_stats;
+ map<RGWObjCategory, RGWBucketStats> calculated_stats;
+
+ int r = store->bucket_check_index(bucket, &existing_stats, &calculated_stats);
+ if (r < 0) {
+ cerr << "failed to check index err=" << cpp_strerror(-r) << std::endl;
+ return r;
+ }
+
+ formatter->open_object_section("check_result");
+ formatter->open_object_section("existing_header");
+ dump_bucket_usage(existing_stats, formatter);
+ formatter->close_section();
+ formatter->open_object_section("calculated_header");
+ dump_bucket_usage(calculated_stats, formatter);
+ formatter->close_section();
+ formatter->close_section();
+ formatter->flush(cout);
+
+ if (fix) {
+ r = store->bucket_rebuild_index(bucket);
+ if (r < 0) {
+ cerr << "failed to rebuild index err=" << cpp_strerror(-r) << std::endl;
+ return r;
+ }
+ }
+ }
+
if (opt_cmd == OPT_BUCKET_RM) {
-- int ret = remove_bucket(bucket, delete_child_objects);
++ int ret = remove_bucket(store, bucket, delete_child_objects);
if (ret < 0) {
cerr << "ERROR: bucket remove returned: " << cpp_strerror(-ret) << std::endl;
uint64_t max_req_id;
public:
- RGWProcess(CephContext *cct, RGWRados *rgwstore, int num_threads)
- RGWProcess(CephContext *cct, int num_threads, RGWREST *_rest)
- : m_tp(cct, "RGWProcess::m_tp", num_threads),
++ RGWProcess(CephContext *cct, RGWRados *rgwstore, int num_threads, RGWREST *_rest)
+ : store(rgwstore), m_tp(cct, "RGWProcess::m_tp", num_threads),
req_throttle(cct, "rgw_ops", num_threads * 2),
+ rest(_rest),
req_wq(this, g_conf->rgw_op_thread_timeout,
g_conf->rgw_op_thread_suicide_timeout, &m_tp),
max_req_id(0) {}
RGWOp *op = NULL;
int init_error = 0;
- RGWHandler *handler = rest.get_handler(store, s, fcgx, &init_error);
- RGWHandler *handler = rest->get_handler(s, &client_io, &init_error);
++ RGWHandler *handler = rest->get_handler(store, s, &client_io, &init_error);
if (init_error != 0) {
abort_early(s, init_error);
goto done;
}
req->log(s, "getting op");
-- op = handler->get_op();
++ op = handler->get_op(store);
if (!op) {
abort_early(s, -ERR_METHOD_NOT_ALLOWED);
goto done;
req->log(s, "executing");
op->execute();
+ op->complete();
done:
- rgw_log_op(s, (op ? op->name() : "unknown"));
+ rgw_log_op(store, s, (op ? op->name() : "unknown"));
int http_ret = s->err.http_ret;
req->log_format(s, "http status=%d", http_ret);
- handler->put_op(op);
+ if (handler)
+ handler->put_op(op);
+ rest->put_handler(handler);
- rgwstore->destroy_context(s->obj_ctx);
+ store->destroy_context(s->obj_ctx);
FCGX_Finish_r(fcgx);
dout(1) << "====== req done req=" << hex << req << dec << " http_status=" << http_ret << " ======" << dendl;
if (r)
return 1;
- rgw_log_usage_init(g_ceph_context);
+ rgw_log_usage_init(g_ceph_context, store);
- RGWProcess process(g_ceph_context, store, g_conf->rgw_thread_pool_size);
+ RGWREST rest;
+
+ list<string> apis;
+
+ get_str_list(g_conf->rgw_enable_apis, apis);
+
+ map<string, bool> apis_map;
+ for (list<string>::iterator li = apis.begin(); li != apis.end(); ++li) {
+ apis_map[*li] = true;
+ }
+
+ if (apis_map.count("s3") > 0)
+ rest.register_default_mgr(new RGWRESTMgr_S3);
+
+ if (apis_map.count("swift") > 0)
+ rest.register_resource(g_conf->rgw_swift_url_prefix, new RGWRESTMgr_SWIFT);
+
+ if (apis_map.count("swift_auth") > 0)
+ rest.register_resource(g_conf->rgw_swift_auth_entry, new RGWRESTMgr_SWIFT_Auth);
+
+ if (apis_map.count("admin") > 0) {
+ RGWRESTMgr_Admin *admin_resource = new RGWRESTMgr_Admin;
+ admin_resource->register_resource("usage", new RGWRESTMgr_Usage);
+ rest.register_resource(g_conf->rgw_admin_entry, admin_resource);
+ }
+
- RGWProcess process(g_ceph_context, g_conf->rgw_thread_pool_size, &rest);
++ RGWProcess process(g_ceph_context, store, g_conf->rgw_thread_pool_size, &rest);
process.run();
rgw_log_usage_finalize();
{
ret = get_params();
if (ret < 0)
- goto done;
+ return;
- ret = rgw_read_user_buckets(s->user.user_id, buckets, !!(s->prot_flags & RGW_REST_SWIFT));
+ ret = rgw_read_user_buckets(store, s->user.user_id, buckets, !!(s->prot_flags & RGW_REST_SWIFT));
if (ret < 0) {
/* hmm.. something wrong here.. the user was authenticated, so it
should exist, just try to recreate */
ret = get_params();
if (ret < 0)
- goto done;
+ return;
- ret = rgwstore->list_objects(s->bucket, max, prefix, delimiter, marker, objs, common_prefixes,
+ ret = store->list_objects(s->bucket, max, prefix, delimiter, marker, objs, common_prefixes,
!!(s->prot_flags & RGW_REST_SWIFT), no_ns, &is_truncated, NULL);
-
- done:
- send_response();
}
int RGWCreateBucket::verify_permission()
ret = get_params();
if (ret < 0)
- goto done;
+ return;
s->bucket_owner = s->user.user_id;
- r = get_policy_from_attr(s->cct, s->obj_ctx, &old_policy, obj);
+ r = get_policy_from_attr(s->cct, store, s->obj_ctx, &old_policy, obj);
if (r >= 0) {
if (old_policy.get_owner().get_id().compare(s->user.user_id) != 0) {
ret = -EEXIST;
rgw_get_request_metadata(s, attrs);
/* check if obj exists, read orig attrs */
- ret = get_obj_attrs(s, obj, orig_attrs, NULL);
+ ret = get_obj_attrs(store, s, obj, orig_attrs, NULL);
if (ret < 0)
- goto done;
+ return;
/* only remove meta attrs */
for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) {
policy.encode(bl);
attrs[RGW_ATTR_ACL] = bl;
}
- ret = rgwstore->set_attrs(s->obj_ctx, obj, attrs, &rmattrs);
+ ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs);
-
- done:
- send_response();
}
int RGWDeleteObj::verify_permission()
ret = -EINVAL;
rgw_obj obj(s->bucket, s->object_str);
if (s->object) {
- rgwstore->set_atomic(s->obj_ctx, obj);
- ret = rgwstore->delete_obj(s->obj_ctx, obj);
+ store->set_atomic(s->obj_ctx, obj);
+ ret = store->delete_obj(s->obj_ctx, obj);
}
-
- send_response();
}
bool RGWCopyObj::parse_copy_location(const char *src, string& bucket_name, string& object)
obj.init_ns(s->bucket, tmp_obj_name, mp_ns);
// the meta object will be indexed with 0 size, we c
- ret = rgwstore->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL);
+ ret = store->put_obj_meta(s->obj_ctx, obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MULTIMETA, true, NULL, NULL, NULL, NULL);
} while (ret == -EEXIST);
- done:
- send_response();
}
-static int get_multiparts_info(struct req_state *s, string& meta_oid, map<uint32_t, RGWUploadPartInfo>& parts,
+static int get_multiparts_info(RGWRados *store, struct req_state *s, string& meta_oid, map<uint32_t, RGWUploadPartInfo>& parts,
RGWAccessControlPolicy& policy, map<string, bufferlist>& attrs)
{
map<string, bufferlist> parts_map;
attrs[RGW_ATTR_ETAG] = etag_bl;
target_obj.init(s->bucket, s->object_str);
- rgwstore->set_atomic(s->obj_ctx, target_obj);
- ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL);
+ store->set_atomic(s->obj_ctx, target_obj);
+ ret = store->put_obj_meta(s->obj_ctx, target_obj, 0, NULL, attrs, RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, NULL, NULL);
if (ret < 0)
- goto done;
+ return;
for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
string oid = mp.get_part(obj_iter->second.num);
manifest.obj_size = ofs;
- rgwstore->set_atomic(s->obj_ctx, target_obj);
+ store->set_atomic(s->obj_ctx, target_obj);
- ret = rgwstore->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs,
- RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest);
+ ret = store->put_obj_meta(s->obj_ctx, target_obj, ofs, NULL, attrs,
+ RGW_OBJ_CATEGORY_MAIN, false, NULL, NULL, &manifest, NULL);
if (ret < 0)
- goto done;
+ return;
// remove the upload obj
meta_obj.init_ns(s->bucket, meta_oid, mp_ns);
- rgwstore->delete_obj(s->obj_ctx, meta_obj);
+ store->delete_obj(s->obj_ctx, meta_obj);
-
- done:
- send_response();
}
int RGWAbortMultipart::verify_permission()
mp.init(s->object_str, upload_id);
meta_oid = mp.get_meta();
- ret = get_multiparts_info(s, meta_oid, obj_parts, policy, attrs);
+ ret = get_multiparts_info(store, s, meta_oid, obj_parts, policy, attrs);
if (ret < 0)
- goto done;
+ return;
for (obj_iter = obj_parts.begin(); obj_iter != obj_parts.end(); ++obj_iter) {
string oid = mp.get_part(obj_iter->second.num);
rgw_obj obj;
obj.init_ns(s->bucket, oid, mp_ns);
- ret = rgwstore->delete_obj(s->obj_ctx, obj);
+ ret = store->delete_obj(s->obj_ctx, obj);
if (ret < 0 && ret != -ENOENT)
- goto done;
+ return;
}
// and also remove the metadata obj
meta_obj.init_ns(s->bucket, meta_oid, mp_ns);
mp.init(s->object_str, upload_id);
meta_oid = mp.get_meta();
- ret = get_multiparts_info(s, meta_oid, parts, policy, xattrs);
+ ret = get_multiparts_info(store, s, meta_oid, parts, policy, xattrs);
-
- done:
- send_response();
}
int RGWListBucketMultiparts::verify_permission()
}
- int RGWHandler::init(RGWRados *_store, struct req_state *_s, FCGX_Request *fcgx)
+ RGWHandler::~RGWHandler()
+ {
+ }
+
-int RGWHandler::init(struct req_state *_s, RGWClientIO *cio)
++int RGWHandler::init(RGWRados *_store, struct req_state *_s, RGWClientIO *cio)
{
+ store = _store;
s = _s;
if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
return ret;
}
-RGWOp *RGWHandler::get_op()
+
- op->init(s, this);
++RGWOp *RGWHandler::get_op(RGWRados *store)
+ {
+ RGWOp *op;
+ switch (s->op) {
+ case OP_GET:
+ op = op_get();
+ break;
+ case OP_PUT:
+ op = op_put();
+ break;
+ case OP_DELETE:
+ op = op_delete();
+ break;
+ case OP_HEAD:
+ op = op_head();
+ break;
+ case OP_POST:
+ op = op_post();
+ break;
+ case OP_COPY:
+ op = op_copy();
+ break;
+ default:
+ return NULL;
+ }
+
+ if (op) {
++ op->init(store, s, this);
+ }
+ return op;
+ }
+
+ void RGWHandler::put_op(RGWOp *op)
+ {
+ delete op;
+ }
+
RGWUserBuckets buckets;
public:
- virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
- RGWOp::init(store, s, h);
- buckets.clear();
- }
-- RGWListBuckets() {}
++ RGWListBuckets() : ret(0) {}
int verify_permission();
void execute();
int verify_permission();
void execute();
- virtual void init(struct req_state *s, RGWHandler *h) {
- RGWOp::init(s, h);
+ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
+ RGWOp::init(store, s, h);
policy.set_ctx(s->cct);
- ret = 0;
}
virtual int get_params() { return 0; }
virtual void send_response() = 0;
int ret;
public:
- RGWDeleteBucket() {}
- RGWDeleteBucket() {
- ret = 0;
- }
++ RGWDeleteBucket() : ret(0) {}
- virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
- RGWOp::init(store, s, h);
- ret = 0;
- }
int verify_permission();
void execute();
ofs = 0;
supplied_md5_b64 = NULL;
supplied_etag = NULL;
- etag = "";
chunked_upload = false;
obj_manifest = NULL;
- virtual void init(struct req_state *s, RGWHandler *h) {
- RGWOp::init(s, h);
+ }
+
++ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
++ RGWOp::init(store, s, h);
policy.set_ctx(s->cct);
}
RGWAccessControlPolicy policy;
public:
- RGWPutMetadata() {}
+ RGWPutMetadata() {
+ has_policy = false;
+ ret = 0;
+ }
- virtual void init(struct req_state *s, RGWHandler *h) {
- RGWOp::init(s, h);
+ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
+ RGWOp::init(store, s, h);
- has_policy = false;
- ret = 0;
policy.set_ctx(s->cct);
}
int verify_permission();
int ret;
public:
- RGWDeleteObj() {}
- RGWDeleteObj() {
- ret = 0;
- }
++ RGWDeleteObj() : ret(0) {}
- virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
- RGWOp::init(store, s, h);
- ret = 0;
- }
int verify_permission();
void execute();
ofs = 0;
len = 0;
end = -1;
++ mod_time = 0;
++ unmod_time = 0;
mod_ptr = NULL;
unmod_ptr = NULL;
ret = 0;
- attrs.clear();
- src_bucket.clear();
- src_object.clear();
mtime = 0;
replace_attrs = false;
- virtual void init(struct req_state *s, RGWHandler *h) {
- RGWOp::init(s, h);
+ }
+
++ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
++ RGWOp::init(store, s, h);
dest_policy.set_ctx(s->cct);
}
int verify_permission();
string acls;
public:
- RGWGetACLs() {}
- RGWGetACLs() {
- ret = 0;
- }
++ RGWGetACLs() : ret(0) {}
- virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
- RGWOp::init(store, s, h);
- ret = 0;
- acls.clear();
- }
int verify_permission();
void execute();
RGWAccessControlPolicy policy;
public:
- RGWInitMultipart() {}
+ RGWInitMultipart() {
+ ret = 0;
+ }
- virtual void init(struct req_state *s, RGWHandler *h) {
- RGWOp::init(s, h);
+ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
+ RGWOp::init(store, s, h);
- ret = 0;
- upload_id = "";
policy.set_ctx(s->cct);
}
int verify_permission();
int ret;
public:
- RGWAbortMultipart() {}
- RGWAbortMultipart() {
- ret = 0;
- }
++ RGWAbortMultipart() : ret(0) {}
- virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
- RGWOp::init(store, s, h);
- ret = 0;
- }
int verify_permission();
void execute();
RGWAccessControlPolicy policy;
public:
- RGWListMultipart() {}
-
- virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
- RGWOp::init(store, s, h);
+ RGWListMultipart() {
ret = 0;
- upload_id = "";
- parts.clear();
max_parts = 1000;
marker = 0;
- virtual void init(struct req_state *s, RGWHandler *h) {
- RGWOp::init(s, h);
+ }
+
++ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
++ RGWOp::init(store, s, h);
policy = RGWAccessControlPolicy(s->cct);
}
int verify_permission();
int default_max;
public:
- RGWListBucketMultiparts() {}
+ RGWListBucketMultiparts() {
- max_uploads = default_max;
- max_uploads = default_max;
+ ret = 0;
+ is_truncated = false;
+ }
+
+ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
+ RGWOp::init(store, s, h);
- prefix.clear();
- marker.clear();
- next_marker.clear();
+ max_uploads = default_max;
- delimiter.clear();
- max_uploads = default_max;
- ret = 0;
- uploads.clear();
- is_truncated = false;
- common_prefixes.clear();
+ }
++
int verify_permission();
void execute();
struct req_state *s;
int do_read_permissions(RGWOp *op, bool only_bucket);
+
+ virtual RGWOp *op_get() { return NULL; }
+ virtual RGWOp *op_put() { return NULL; }
+ virtual RGWOp *op_delete() { return NULL; }
+ virtual RGWOp *op_head() { return NULL; }
+ virtual RGWOp *op_post() { return NULL; }
+ virtual RGWOp *op_copy() { return NULL; }
public:
RGWHandler() {}
- virtual ~RGWHandler() {}
- virtual int init(RGWRados *store, struct req_state *_s, FCGX_Request *fcgx);
+ virtual ~RGWHandler();
- virtual int init(struct req_state *_s, RGWClientIO *cio);
++ virtual int init(RGWRados *store, struct req_state *_s, RGWClientIO *cio);
- virtual RGWOp *get_op() = 0;
- virtual void put_op(RGWOp *op) = 0;
- virtual RGWOp *get_op();
++ virtual RGWOp *get_op(RGWRados *store);
+ virtual void put_op(RGWOp *op);
virtual int read_permissions(RGWOp *op) = 0;
virtual int authorize() = 0;
};
RGWRESTMgr::~RGWRESTMgr()
{
- delete m_os_handler;
- delete m_os_auth_handler;
- delete m_s3_handler;
+ map<string, RGWRESTMgr *>::iterator iter;
+ for (iter = resource_mgrs.begin(); iter != resource_mgrs.end(); ++iter) {
+ delete iter->second;
+ }
+ delete default_mgr;
}
- RGWHandler *RGWRESTMgr::get_handler(RGWRados *store, struct req_state *s, FCGX_Request *fcgx,
- int *init_error)
+ int RGWREST::preprocess(struct req_state *s, RGWClientIO *cio)
{
- RGWHandler *handler;
+ s->cio = cio;
+ s->request_uri = s->env->get("REQUEST_URI");
+ int pos = s->request_uri.find('?');
+ if (pos >= 0) {
+ s->request_params = s->request_uri.substr(pos + 1);
+ s->request_uri = s->request_uri.substr(0, pos);
+ }
+ s->host = s->env->get("HTTP_HOST");
+ if (g_conf->rgw_dns_name.length() && s->host) {
+ string h(s->host);
- *init_error = RGWHandler_REST::preprocess(s, fcgx);
+ ldout(s->cct, 10) << "host=" << s->host << " rgw_dns_name=" << g_conf->rgw_dns_name << dendl;
+ pos = h.find(g_conf->rgw_dns_name);
- if (s->prot_flags & RGW_REST_SWIFT)
- handler = m_os_handler;
- else if (s->prot_flags & RGW_REST_SWIFT_AUTH)
- handler = m_os_auth_handler;
- else
- handler = m_s3_handler;
+ if (pos > 0 && h[pos - 1] == '.') {
+ string encoded_bucket = "/";
+ encoded_bucket.append(h.substr(0, pos-1));
+ if (s->request_uri[0] != '/')
+ encoded_bucket.append("/'");
+ encoded_bucket.append(s->request_uri);
+ s->request_uri = encoded_bucket;
+ }
+ }
- handler->init(store, s, fcgx);
+ url_decode(s->request_uri, s->decoded_uri);
+ s->method = s->env->get("REQUEST_METHOD");
+ s->length = s->env->get("CONTENT_LENGTH");
+ if (s->length) {
+ if (*s->length == '\0')
+ return -EINVAL;
+ s->content_length = atoll(s->length);
+ }
- return handler;
+ s->content_type = s->env->get("CONTENT_TYPE");
+ s->http_auth = s->env->get("HTTP_AUTHORIZATION");
+
+ if (g_conf->rgw_print_continue) {
+ const char *expect = s->env->get("HTTP_EXPECT");
+ s->expect_cont = (expect && !strcasecmp(expect, "100-continue"));
+ }
+ s->op = op_from_method(s->method);
+
+ init_meta_info(s);
+
+ return 0;
}
- void RGWHandler_REST::put_op(RGWOp *op)
-RGWHandler *RGWREST::get_handler(struct req_state *s, RGWClientIO *cio,
++RGWHandler *RGWREST::get_handler(RGWRados *store, struct req_state *s, RGWClientIO *cio,
+ int *init_error)
{
- delete op;
+ RGWHandler *handler;
+
+ *init_error = preprocess(s, cio);
+ if (*init_error < 0)
+ return NULL;
+
+ RGWRESTMgr *m = mgr.get_resource_mgr(s, s->decoded_uri);
+ if (!m) {
+ *init_error = -ERR_METHOD_NOT_ALLOWED;
+ return NULL;
+ }
+
+ handler = m->get_handler(s);
+ if (!handler) {
+ *init_error = -ERR_METHOD_NOT_ALLOWED;
+ return NULL;
+ }
- *init_error = handler->init(s, cio);
++ *init_error = handler->init(store, s, cio);
+ if (*init_error < 0)
+ return NULL;
+
+ return handler;
}
protected:
bool sent_header;
public:
- RGWGetObj_REST() : sent_header(false) {}
+ RGWGetObj_ObjStore() : sent_header(false) {}
- virtual void init(struct req_state *s, RGWHandler *h) {
- RGWGetObj::init(s, h);
+ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) {
+ RGWGetObj::init(store, s, h);
sent_header = false;
}
int get_params();
};
- class RGWHandler_REST : public RGWHandler {
+ class RGWRESTOp : public RGWOp {
protected:
- virtual bool is_acl_op() = 0;
- virtual bool is_obj_update_op() = 0;
-
- virtual RGWOp *get_retrieve_obj_op(bool get_data) = 0;
- virtual RGWOp *get_retrieve_op(bool get_data) = 0;
- virtual RGWOp *get_create_op() = 0;
- virtual RGWOp *get_delete_op() = 0;
- virtual RGWOp *get_post_op() = 0;
- virtual RGWOp *get_copy_op() = 0;
+ int http_ret;
+ RGWRESTFlusher flusher;
+ public:
+ RGWRESTOp() : http_ret(0) {}
- virtual void init(struct req_state *s, RGWHandler *dialect_handler) {
- RGWOp::init(s, dialect_handler);
++ virtual void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) {
++ RGWOp::init(store, s, dialect_handler);
+ flusher.init(s);
+ }
+ virtual void send_response();
+ virtual int check_caps(RGWUserCaps& caps) { return -EPERM; } /* should to be implemented! */
+ virtual int verify_permission();
+ };
+ class RGWHandler_ObjStore : public RGWHandler {
+ protected:
+ virtual bool is_obj_update_op() { return false; }
+ virtual RGWOp *op_get() { return NULL; }
+ virtual RGWOp *op_put() { return NULL; }
+ virtual RGWOp *op_delete() { return NULL; }
+ virtual RGWOp *op_head() { return NULL; }
+ virtual RGWOp *op_post() { return NULL; }
+ virtual RGWOp *op_copy() { return NULL; }
+
+ virtual int validate_bucket_name(const string& bucket);
+ virtual int validate_object_name(const string& object);
+
+ static int allocate_formatter(struct req_state *s, int default_formatter, bool configurable);
public:
+ RGWHandler_ObjStore() {}
+ virtual ~RGWHandler_ObjStore() {}
int read_permissions(RGWOp *op);
- RGWOp *get_op();
- void put_op(RGWOp *op);
- static int preprocess(struct req_state *s, FCGX_Request *fcgx);
virtual int authorize() = 0;
};
- class RGWHandler_REST_SWIFT;
+ class RGWHandler_ObjStore_SWIFT;
class RGWHandler_SWIFT_Auth;
- class RGWHandler_REST_S3;
+ class RGWHandler_ObjStore_S3;
class RGWRESTMgr {
- RGWHandler_REST_SWIFT *m_os_handler;
- RGWHandler_SWIFT_Auth *m_os_auth_handler;
- RGWHandler_REST_S3 *m_s3_handler;
+ protected:
+ map<string, RGWRESTMgr *> resource_mgrs;
+ multimap<size_t, string> resources_by_size;
+ RGWRESTMgr *default_mgr;
+
+ public:
+ RGWRESTMgr() : default_mgr(NULL) {}
+ virtual ~RGWRESTMgr();
+
+ void register_resource(string resource, RGWRESTMgr *mgr);
+ void register_default_mgr(RGWRESTMgr *mgr);
+
+ virtual RGWRESTMgr *get_resource_mgr(struct req_state *s, const string& uri);
+ virtual RGWHandler *get_handler(struct req_state *s) { return NULL; }
+ virtual void put_handler(RGWHandler *handler) { delete handler; }
+ };
+
+ class RGWREST {
+ RGWRESTMgr mgr;
+ static int preprocess(struct req_state *s, RGWClientIO *cio);
public:
- RGWRESTMgr();
- ~RGWRESTMgr();
- RGWHandler *get_handler(RGWRados *store, struct req_state *s, FCGX_Request *fcgx,
+ RGWREST() {}
- RGWHandler *get_handler(struct req_state *s, RGWClientIO *cio,
++ RGWHandler *get_handler(RGWRados *store, struct req_state *s, RGWClientIO *cio,
int *init_error);
+ void put_handler(RGWHandler *handler) {
+ mgr.put_handler(handler);
+ }
+
+ void register_resource(string resource, RGWRESTMgr *m, bool register_empty = false) {
+ if (!register_empty && resource.empty())
+ return;
+
+ mgr.register_resource(resource, m);
+ }
+ void register_default_mgr(RGWRESTMgr *m) {
+ mgr.register_default_mgr(m);
+ }
};
extern void set_req_state_err(struct req_state *s, int err_no);
{
string upload_id = s->args.get("uploadId");
- if (s->object) {
- if (upload_id.empty())
- return new RGWDeleteObj_REST_S3;
- else
- return new RGWAbortMultipart_REST_S3;
- } else if (s->bucket_name)
- return new RGWDeleteBucket_REST_S3;
+ if (upload_id.empty())
+ return new RGWDeleteObj_ObjStore_S3;
+ else
+ return new RGWAbortMultipart_ObjStore_S3;
+ }
- return NULL;
+ RGWOp *RGWHandler_ObjStore_Obj_S3::op_post()
+ {
+ if (s->args.exists("uploadId"))
+ return new RGWCompleteMultipart_ObjStore_S3;
+ else
+ return new RGWInitMultipart_ObjStore_S3;
}
- RGWOp *RGWHandler_REST_S3::get_post_op()
+ int RGWHandler_ObjStore_S3::init_from_header(struct req_state *s, int default_formatter, bool configurable_format)
{
- if (s->object) {
- if (s->args.exists("uploadId"))
- return new RGWCompleteMultipart_REST_S3;
- else
- return new RGWInitMultipart_REST_S3;
+ string req;
+ string first;
+
+ const char *req_name = s->decoded_uri.c_str();
+ const char *p;
+
+ if (*req_name == '?') {
+ p = req_name;
+ } else {
+ p = s->request_params.c_str();
}
- else if (s->args.sub_resource_exists("delete")) {
- return new RGWDeleteMultiObj_REST_S3;
+
+ s->args.set(p);
+ s->args.parse();
+
+ /* must be called after the args parsing */
+ int ret = allocate_formatter(s, default_formatter, configurable_format);
+ if (ret < 0)
+ return ret;
+
+ if (*req_name != '/')
+ return 0;
+
+ req_name++;
+
+ if (!*req_name)
+ return 0;
+
+ req = req_name;
+ int pos = req.find('/');
+ if (pos >= 0) {
+ first = req.substr(0, pos);
+ } else {
+ first = req;
}
- return NULL;
+ if (!s->bucket_name) {
+ s->bucket_name_str = first;
+ s->bucket_name = strdup(s->bucket_name_str.c_str());
+
+ if (pos >= 0) {
+ string encoded_obj_str = req.substr(pos+1);
+ s->object_str = encoded_obj_str;
+
+ if (s->object_str.size() > 0) {
+ s->object = strdup(s->object_str.c_str());
+ }
+ }
+ } else {
+ s->object_str = req_name;
+ s->object = strdup(s->object_str.c_str());
+ }
+ return 0;
}
- int RGWHandler_REST_S3::init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx)
+ static bool looks_like_ip_address(const char *bucket)
{
- const char *cacl = state->env->get("HTTP_X_AMZ_ACL");
+ int num_periods = 0;
+ bool expect_period = false;
+ for (const char *b = bucket; *b; ++b) {
+ if (*b == '.') {
+ if (!expect_period)
+ return false;
+ ++num_periods;
+ if (num_periods > 3)
+ return false;
+ expect_period = false;
+ }
+ else if (isdigit(*b)) {
+ expect_period = true;
+ }
+ else {
+ return false;
+ }
+ }
+ return (num_periods == 3);
+ }
+
+ int RGWHandler_ObjStore_S3::validate_bucket_name(const string& bucket)
+ {
+ int ret = RGWHandler_ObjStore::validate_bucket_name(bucket);
+ if (ret < 0)
+ return ret;
+
+ if (bucket.size() == 0)
+ return 0;
+
+ if (!(isalpha(bucket[0]) || isdigit(bucket[0]))) {
+ // bucket names must start with a number or letter
+ return -ERR_INVALID_BUCKET_NAME;
+ }
+
+ for (const char *s = bucket.c_str(); *s; ++s) {
+ char c = *s;
+ if (isdigit(c) || (c == '.'))
+ continue;
+ if (isalpha(c))
+ continue;
+ if ((c == '-') || (c == '_'))
+ continue;
+ // Invalid character
+ return -ERR_INVALID_BUCKET_NAME;
+ }
+
+ if (looks_like_ip_address(bucket.c_str()))
+ return -ERR_INVALID_BUCKET_NAME;
+
+ return 0;
+ }
+
-int RGWHandler_ObjStore_S3::init(struct req_state *s, RGWClientIO *cio)
++int RGWHandler_ObjStore_S3::init(RGWRados *store, struct req_state *s, RGWClientIO *cio)
+ {
+ dout(10) << "s->object=" << (s->object ? s->object : "<NULL>") << " s->bucket=" << (s->bucket_name ? s->bucket_name : "<NULL>") << dendl;
+
+ int ret = validate_bucket_name(s->bucket_name_str);
+ if (ret)
+ return ret;
+ ret = validate_object_name(s->object_str);
+ if (ret)
+ return ret;
+
+ const char *cacl = s->env->get("HTTP_X_AMZ_ACL");
if (cacl)
- state->canned_acl = cacl;
+ s->canned_acl = cacl;
- state->copy_source = state->env->get("HTTP_X_AMZ_COPY_SOURCE");
+ s->copy_source = s->env->get("HTTP_X_AMZ_COPY_SOURCE");
- state->dialect = "s3";
+ s->dialect = "s3";
- return RGWHandler_REST::init(store, state, fcgx);
- return RGWHandler_ObjStore::init(s, cio);
++ return RGWHandler_ObjStore::init(store, s, cio);
}
/*
* verify that a signed request comes from the keyholder
* by checking the signature against our locally-computed version
*/
- int RGWHandler_REST_S3::authorize()
-int RGW_Auth_S3::authorize(struct req_state *s)
++int RGW_Auth_S3::authorize(RGWRados *store, struct req_state *s)
{
bool qsr = false;
string auth_id;
return 0;
}
-int RGWHandler_Auth_S3::init(struct req_state *state, RGWClientIO *cio)
++int RGWHandler_Auth_S3::init(RGWRados *store, struct req_state *state, RGWClientIO *cio)
+ {
+ int ret = RGWHandler_ObjStore_S3::init_from_header(state, RGW_FORMAT_JSON, true);
+ if (ret < 0)
+ return ret;
- return RGWHandler_ObjStore::init(state, cio);
++ return RGWHandler_ObjStore::init(store, state, cio);
+ }
+
+ RGWHandler *RGWRESTMgr_S3::get_handler(struct req_state *s)
+ {
+ int ret = RGWHandler_ObjStore_S3::init_from_header(s, RGW_FORMAT_XML, false);
+ if (ret < 0)
+ return NULL;
+
+ if (!s->bucket_name)
+ return new RGWHandler_ObjStore_Service_S3;
+
+ if (!s->object)
+ return new RGWHandler_ObjStore_Bucket_S3;
+
+ return new RGWHandler_ObjStore_Obj_S3;
+ }
void end_response();
};
- static int authorize(struct req_state *s);
+ class RGW_Auth_S3 {
+ public:
- virtual int init(struct req_state *state, RGWClientIO *cio);
++ static int authorize(RGWRados *store, struct req_state *s);
+ };
+
+ class RGWHandler_Auth_S3 : public RGWHandler_ObjStore {
+ friend class RGWRESTMgr_S3;
+ public:
+ RGWHandler_Auth_S3() : RGWHandler_ObjStore() {}
+ virtual ~RGWHandler_Auth_S3() {}
+
+ virtual int validate_bucket_name(const string& bucket) { return 0; }
+ virtual int validate_object_name(const string& bucket) { return 0; }
+
- return RGW_Auth_S3::authorize(s);
++ virtual int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
+ virtual int authorize() {
++ return RGW_Auth_S3::authorize(store, s);
+ }
+ };
+
+ class RGWHandler_ObjStore_S3 : public RGWHandler_ObjStore {
+ friend class RGWRESTMgr_S3;
+ public:
+ static int init_from_header(struct req_state *s, int default_formatter, bool configurable_format);
+
+ RGWHandler_ObjStore_S3() : RGWHandler_ObjStore() {}
+ virtual ~RGWHandler_ObjStore_S3() {}
+
+ int validate_bucket_name(const string& bucket);
- class RGWHandler_REST_S3 : public RGWHandler_REST {
- virtual int init(struct req_state *state, RGWClientIO *cio);
++ virtual int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
+ virtual int authorize() {
- return RGW_Auth_S3::authorize(s);
++ return RGW_Auth_S3::authorize(store, s);
+ }
+ };
+
+ class RGWHandler_ObjStore_Service_S3 : public RGWHandler_ObjStore_S3 {
+ protected:
+ RGWOp *op_get();
+ RGWOp *op_head();
+ public:
+ RGWHandler_ObjStore_Service_S3() {}
+ virtual ~RGWHandler_ObjStore_Service_S3() {}
+ };
+
+ class RGWHandler_ObjStore_Bucket_S3 : public RGWHandler_ObjStore_S3 {
protected:
bool is_acl_op() {
return s->args.exists("acl");
}
if (get_data)
- return new RGWListBucket_REST_SWIFT;
+ return new RGWListBucket_ObjStore_SWIFT;
else
- return new RGWStatBucket_REST_SWIFT;
+ return new RGWStatBucket_ObjStore_SWIFT;
}
- RGWOp *RGWHandler_REST_SWIFT::get_retrieve_op(bool get_data)
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_get()
{
- if (s->bucket_name) {
- if (is_acl_op()) {
- return new RGWGetACLs_REST_SWIFT;
- }
- return get_retrieve_obj_op(get_data);
+ if (is_acl_op()) {
+ return new RGWGetACLs_ObjStore_SWIFT;
}
+ return get_obj_op(true);
+ }
- if (get_data)
- return new RGWListBuckets_REST_SWIFT;
- else
- return new RGWStatAccount_REST_SWIFT;
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_head()
+ {
+ if (is_acl_op()) {
+ return new RGWGetACLs_ObjStore_SWIFT;
+ }
+ return get_obj_op(false);
}
- RGWOp *RGWHandler_REST_SWIFT::get_create_op()
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_put()
{
if (is_acl_op()) {
- return new RGWPutACLs_REST_SWIFT;
- } else if (s->object) {
- if (!s->copy_source)
- return new RGWPutObj_REST_SWIFT;
- else
- return new RGWCopyObj_REST_SWIFT;
- } else if (s->bucket_name) {
- return new RGWCreateBucket_REST_SWIFT;
+ return new RGWPutACLs_ObjStore_SWIFT;
}
+ return new RGWCreateBucket_ObjStore_SWIFT;
+ }
+
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_delete()
+ {
+ return new RGWDeleteBucket_ObjStore_SWIFT;
+ }
- return NULL;
+ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_post()
+ {
+ return new RGWPutMetadata_ObjStore_SWIFT;
}
- RGWOp *RGWHandler_REST_SWIFT::get_delete_op()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::get_obj_op(bool get_data)
{
- if (s->object)
- return new RGWDeleteObj_REST_SWIFT;
- else if (s->bucket_name)
- return new RGWDeleteBucket_REST_SWIFT;
+ if (is_acl_op()) {
+ return new RGWGetACLs_ObjStore_SWIFT;
+ }
- return NULL;
+ RGWGetObj_ObjStore_SWIFT *get_obj_op = new RGWGetObj_ObjStore_SWIFT;
+ get_obj_op->set_get_data(get_data);
+ return get_obj_op;
}
- RGWOp *RGWHandler_REST_SWIFT::get_post_op()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_get()
{
- return new RGWPutMetadata_REST_SWIFT;
+ if (is_acl_op()) {
+ return new RGWGetACLs_ObjStore_SWIFT;
+ }
+ return get_obj_op(true);
}
- RGWOp *RGWHandler_REST_SWIFT::get_copy_op()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_head()
{
- if (s->object)
- return new RGWCopyObj_REST_SWIFT;
+ if (is_acl_op()) {
+ return new RGWGetACLs_ObjStore_SWIFT;
+ }
+ return get_obj_op(false);
+ }
+
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_put()
+ {
+ if (is_acl_op()) {
+ return new RGWPutACLs_ObjStore_SWIFT;
+ }
+ if (!s->copy_source)
+ return new RGWPutObj_ObjStore_SWIFT;
+ else
+ return new RGWCopyObj_ObjStore_SWIFT;
+ }
- return NULL;
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_delete()
+ {
+ return new RGWDeleteObj_ObjStore_SWIFT;
}
- int RGWHandler_REST_SWIFT::authorize()
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_post()
+ {
+ return new RGWPutMetadata_ObjStore_SWIFT;
+ }
+
+ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_copy()
+ {
+ return new RGWCopyObj_ObjStore_SWIFT;
+ }
+
+ int RGWHandler_ObjStore_SWIFT::authorize()
{
- bool authorized = rgw_verify_os_token(s);
+ bool authorized = rgw_verify_swift_token(store, s);
if (!authorized)
return -EPERM;
return 0;
}
- int RGWHandler_REST_SWIFT::init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx)
+ int RGWHandler_ObjStore_SWIFT::validate_bucket_name(const string& bucket)
+ {
+ int ret = RGWHandler_ObjStore::validate_bucket_name(bucket);
+ if (ret < 0)
+ return ret;
+
+ int len = bucket.size();
+
+ if (len == 0)
+ return 0;
+
+ if (bucket[0] == '.')
+ return -ERR_INVALID_BUCKET_NAME;
+
+ if (check_utf8(bucket.c_str(), len))
+ return -ERR_INVALID_UTF8;
+
+ const char *s = bucket.c_str();
+
+ for (int i = 0; i < len; ++i, ++s) {
+ if (*(unsigned char *)s == 0xff)
+ return -ERR_INVALID_BUCKET_NAME;
+ }
+
+ return 0;
+ }
+
+ static void next_tok(string& str, string& tok, char delim)
+ {
+ if (str.size() == 0) {
+ tok = "";
+ return;
+ }
+ tok = str;
+ int pos = str.find(delim);
+ if (pos > 0) {
+ tok = str.substr(0, pos);
+ str = str.substr(pos + 1);
+ } else {
+ str = "";
+ }
+ }
+
+ int RGWHandler_ObjStore_SWIFT::init_from_header(struct req_state *s)
{
- state->copy_source = state->env->get("HTTP_X_COPY_FROM");
+ string req;
+ string first;
+
+ s->prot_flags |= RGW_REST_SWIFT;
+
+ const char *req_name = s->decoded_uri.c_str();
+ const char *p;
+
+ if (*req_name == '?') {
+ p = req_name;
+ } else {
+ p = s->request_params.c_str();
+ }
+
+ s->args.set(p);
+ s->args.parse();
+
+ if (*req_name != '/')
+ return 0;
+
+ req_name++;
+
+ if (!*req_name)
+ return 0;
+
+ req = req_name;
+
+ int pos = req.find('/');
+ if (pos >= 0) {
+ bool cut_url = g_conf->rgw_swift_url_prefix.length();
+ first = req.substr(0, pos);
+ if (first.compare(g_conf->rgw_swift_url_prefix) == 0) {
+ if (cut_url) {
+ next_tok(req, first, '/');
+ }
+ }
+ } else {
+ if (req.compare(g_conf->rgw_swift_url_prefix) == 0) {
+ s->formatter = new RGWFormatter_Plain;
+ return -ERR_BAD_URL;
+ }
+ first = req;
+ }
+
+ /* verify that the request_uri conforms with what's expected */
+ char buf[g_conf->rgw_swift_url_prefix.length() + 16];
+ int blen = sprintf(buf, "/%s/v1", g_conf->rgw_swift_url_prefix.c_str());
+ if (s->decoded_uri[0] != '/' ||
+ s->decoded_uri.compare(0, blen, buf) != 0) {
+ return -ENOENT;
+ }
+
+ int ret = allocate_formatter(s, RGW_FORMAT_PLAIN, true);
+ if (ret < 0)
+ return ret;
+
+ string ver;
+
+ next_tok(req, ver, '/');
+ s->os_auth_token = s->env->get("HTTP_X_AUTH_TOKEN");
+ next_tok(req, first, '/');
+
+ dout(10) << "ver=" << ver << " first=" << first << " req=" << req << dendl;
+ if (first.size() == 0)
+ return 0;
+
+ s->bucket_name_str = first;
+ s->bucket_name = strdup(s->bucket_name_str.c_str());
+
+ if (req.size()) {
+ s->object_str = req;
+ s->object = strdup(s->object_str.c_str());
+ }
+ return 0;
+ }
+
-int RGWHandler_ObjStore_SWIFT::init(struct req_state *s, RGWClientIO *cio)
++int RGWHandler_ObjStore_SWIFT::init(RGWRados *store, struct req_state *s, RGWClientIO *cio)
+ {
+ dout(10) << "s->object=" << (s->object ? s->object : "<NULL>") << " s->bucket=" << (s->bucket_name ? s->bucket_name : "<NULL>") << dendl;
+
+ int ret = validate_bucket_name(s->bucket_name_str.c_str());
+ if (ret)
+ return ret;
+ ret = validate_object_name(s->object_str.c_str());
+ if (ret)
+ return ret;
+
+ s->copy_source = s->env->get("HTTP_X_COPY_FROM");
+
+ s->dialect = "swift";
+
- return RGWHandler_ObjStore::init(s, cio);
++ return RGWHandler_ObjStore::init(store, s, cio);
+ }
+
+
+ RGWHandler *RGWRESTMgr_SWIFT::get_handler(struct req_state *s)
+ {
+ int ret = RGWHandler_ObjStore_SWIFT::init_from_header(s);
+ if (ret < 0)
+ return NULL;
- state->dialect = "swift";
+ if (!s->bucket_name)
+ return new RGWHandler_ObjStore_Service_SWIFT;
+ if (!s->object)
+ return new RGWHandler_ObjStore_Bucket_SWIFT;
- return RGWHandler_REST::init(store, state, fcgx);
+ return new RGWHandler_ObjStore_Obj_SWIFT;
}
void send_response() {}
};
-
- class RGWHandler_REST_SWIFT : public RGWHandler_REST {
+ class RGWHandler_ObjStore_SWIFT : public RGWHandler_ObjStore {
+ friend class RGWRESTMgr_SWIFT;
protected:
- bool is_acl_op() {
- return false; // for now
+ virtual bool is_acl_op() {
+ return false;
}
- int init(struct req_state *state, RGWClientIO *cio);
+
+ static int init_from_header(struct req_state *s);
+ public:
+ RGWHandler_ObjStore_SWIFT() {}
+ virtual ~RGWHandler_ObjStore_SWIFT() {}
+
+ int validate_bucket_name(const string& bucket);
+
++ int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
+ int authorize();
+
+ RGWAccessControlPolicy *alloc_policy() { return NULL; /* return new RGWAccessControlPolicy_SWIFT; */ }
+ void free_policy(RGWAccessControlPolicy *policy) { delete policy; }
+ };
+
+ class RGWHandler_ObjStore_Service_SWIFT : public RGWHandler_ObjStore_SWIFT {
+ protected:
+ RGWOp *op_get();
+ RGWOp *op_head();
+ public:
+ RGWHandler_ObjStore_Service_SWIFT() {}
+ virtual ~RGWHandler_ObjStore_Service_SWIFT() {}
+ };
+
+ class RGWHandler_ObjStore_Bucket_SWIFT : public RGWHandler_ObjStore_SWIFT {
+ protected:
bool is_obj_update_op() {
return s->op == OP_POST;
}
--- /dev/null
- http_ret = RGWUsage::show(rgwstore, uid, start, end, show_entries, show_summary, &categories, flusher);
+ #include "rgw_op.h"
+ #include "rgw_usage.h"
+ #include "rgw_rest_usage.h"
+
+ #define dout_subsys ceph_subsys_rgw
+
+ class RGWOp_Usage_Get : public RGWRESTOp {
+
+ public:
+ RGWOp_Usage_Get() {}
+
+ int check_caps(RGWUserCaps& caps) {
+ return caps.check_cap("usage", RGW_CAP_READ);
+ }
+ void execute();
+
+ virtual const char *name() { return "get_usage"; }
+ };
+
+ void RGWOp_Usage_Get::execute() {
+ map<std::string, bool> categories;
+
+ string uid;
+ uint64_t start, end;
+ bool show_entries;
+ bool show_summary;
+
+ RESTArgs::get_string(s, "uid", uid, &uid);
+ RESTArgs::get_epoch(s, "start", 0, &start);
+ RESTArgs::get_epoch(s, "end", (uint64_t)-1, &end);
+ RESTArgs::get_bool(s, "show-entries", true, &show_entries);
+ RESTArgs::get_bool(s, "show-summary", true, &show_summary);
+
- http_ret = RGWUsage::trim(rgwstore, uid, start, end);
++ http_ret = RGWUsage::show(store, uid, start, end, show_entries, show_summary, &categories, flusher);
+ }
+
+ class RGWOp_Usage_Delete : public RGWRESTOp {
+
+ public:
+ RGWOp_Usage_Delete() {}
+
+ int check_caps(RGWUserCaps& caps) {
+ return caps.check_cap("usage", RGW_CAP_WRITE);
+ }
+ void execute();
+
+ virtual const char *name() { return "trim_usage"; }
+ };
+
+ void RGWOp_Usage_Delete::execute() {
+ map<std::string, bool> categories;
+
+ string uid;
+ uint64_t start, end;
+
+ RESTArgs::get_string(s, "uid", uid, &uid);
+ RESTArgs::get_epoch(s, "start", 0, &start);
+ RESTArgs::get_epoch(s, "end", (uint64_t)-1, &end);
+
+ if (uid.empty() &&
+ !start &&
+ end == (uint64_t)-1) {
+ bool remove_all;
+ RESTArgs::get_bool(s, "remove-all", false, &remove_all);
+ if (!remove_all) {
+ http_ret = -EINVAL;
+ return;
+ }
+ }
+
++ http_ret = RGWUsage::trim(store, uid, start, end);
+ }
+
+ RGWOp *RGWHandler_Usage::op_get()
+ {
+ return new RGWOp_Usage_Get;
+ };
+
+ RGWOp *RGWHandler_Usage::op_delete()
+ {
+ return new RGWOp_Usage_Delete;
+ };
+
+
end_header(s);
}
- int RGWHandler_SWIFT_Auth::init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx)
-int RGWHandler_SWIFT_Auth::init(struct req_state *state, RGWClientIO *cio)
++int RGWHandler_SWIFT_Auth::init(RGWRados *store, struct req_state *state, RGWClientIO *cio)
{
state->dialect = "swift-auth";
+ state->formatter = new JSONFormatter;
+ state->format = RGW_FORMAT_JSON;
- return RGWHandler::init(store, state, fcgx);
- return RGWHandler::init(state, cio);
++ return RGWHandler::init(store, state, cio);
}
int RGWHandler_SWIFT_Auth::authorize()
public:
RGWHandler_SWIFT_Auth() {}
~RGWHandler_SWIFT_Auth() {}
- RGWOp *get_op();
- void put_op(RGWOp *op);
+ RGWOp *op_get();
- int init(RGWRados *store, struct req_state *state, FCGX_Request *fcgx);
- int init(struct req_state *state, RGWClientIO *cio);
++ int init(RGWRados *store, struct req_state *state, RGWClientIO *cio);
int authorize();
int read_permissions(RGWOp *op) { return 0; }
--- /dev/null
- int ret = rgwstore->read_usage(uid, start_epoch, end_epoch, max_entries,
- &is_truncated, usage_iter, usage);
+
+ #include <string>
+ #include <map>
+
+ #include "rgw_rados.h"
+ #include "rgw_usage.h"
+ #include "rgw_formats.h"
+
+ using namespace std;
+
+
+ static void dump_usage_categories_info(Formatter *formatter, const rgw_usage_log_entry& entry, map<string, bool> *categories)
+ {
+ formatter->open_array_section("categories");
+ map<string, rgw_usage_data>::const_iterator uiter;
+ for (uiter = entry.usage_map.begin(); uiter != entry.usage_map.end(); ++uiter) {
+ if (categories && categories->size() && !categories->count(uiter->first))
+ continue;
+ const rgw_usage_data& usage = uiter->second;
+ formatter->open_object_section("entry");
+ formatter->dump_string("category", uiter->first);
+ formatter->dump_int("bytes_sent", usage.bytes_sent);
+ formatter->dump_int("bytes_received", usage.bytes_received);
+ formatter->dump_int("ops", usage.ops);
+ formatter->dump_int("successful_ops", usage.successful_ops);
+ formatter->close_section(); // entry
+ }
+ formatter->close_section(); // categories
+ }
+
+ int RGWUsage::show(RGWRados *store, string& uid, uint64_t start_epoch,
+ uint64_t end_epoch, bool show_log_entries, bool show_log_sum,
+ map<string, bool> *categories,
+ RGWFormatterFlusher& flusher)
+ {
+ uint32_t max_entries = 1000;
+
+ bool is_truncated = true;
+
+ RGWUsageIter usage_iter;
+ Formatter *formatter = flusher.get_formatter();
+
+ map<rgw_user_bucket, rgw_usage_log_entry> usage;
+
+ flusher.start(0);
+
+ formatter->open_object_section("usage");
+ if (show_log_entries) {
+ formatter->open_array_section("entries");
+ }
+ string last_owner;
+ bool user_section_open = false;
+ map<string, rgw_usage_log_entry> summary_map;
+ while (is_truncated) {
++ int ret = store->read_usage(uid, start_epoch, end_epoch, max_entries,
++ &is_truncated, usage_iter, usage);
+
+ if (ret == -ENOENT) {
+ ret = 0;
+ is_truncated = false;
+ }
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ map<rgw_user_bucket, rgw_usage_log_entry>::iterator iter;
+ for (iter = usage.begin(); iter != usage.end(); ++iter) {
+ const rgw_user_bucket& ub = iter->first;
+ const rgw_usage_log_entry& entry = iter->second;
+
+ if (show_log_entries) {
+ if (ub.user.compare(last_owner) != 0) {
+ if (user_section_open) {
+ formatter->close_section();
+ formatter->close_section();
+ }
+ formatter->open_object_section("user");
+ formatter->dump_string("owner", ub.user);
+ formatter->open_array_section("buckets");
+ user_section_open = true;
+ last_owner = ub.user;
+ }
+ formatter->open_object_section("bucket");
+ formatter->dump_string("bucket", ub.bucket);
+ utime_t ut(entry.epoch, 0);
+ ut.gmtime(formatter->dump_stream("time"));
+ formatter->dump_int("epoch", entry.epoch);
+ dump_usage_categories_info(formatter, entry, categories);
+ formatter->close_section(); // bucket
+ flusher.flush();
+ }
+
+ summary_map[ub.user].aggregate(entry, categories);
+ }
+ }
+ if (show_log_entries) {
+ if (user_section_open) {
+ formatter->close_section(); // buckets
+ formatter->close_section(); //user
+ }
+ formatter->close_section(); // entries
+ }
+
+ if (show_log_sum) {
+ formatter->open_array_section("summary");
+ map<string, rgw_usage_log_entry>::iterator siter;
+ for (siter = summary_map.begin(); siter != summary_map.end(); ++siter) {
+ const rgw_usage_log_entry& entry = siter->second;
+ formatter->open_object_section("user");
+ formatter->dump_string("user", siter->first);
+ dump_usage_categories_info(formatter, entry, categories);
+ rgw_usage_data total_usage;
+ entry.sum(total_usage, *categories);
+ formatter->open_object_section("total");
+ formatter->dump_int("bytes_sent", total_usage.bytes_sent);
+ formatter->dump_int("bytes_received", total_usage.bytes_received);
+ formatter->dump_int("ops", total_usage.ops);
+ formatter->dump_int("successful_ops", total_usage.successful_ops);
+ formatter->close_section(); // total
+
+ formatter->close_section(); // user
+
+ flusher.flush();
+ }
+
+ formatter->close_section(); // summary
+ }
+
+ formatter->close_section(); // usage
+ flusher.flush();
+
+ return 0;
+ }
+
+ int RGWUsage::trim(RGWRados *store, string& uid, uint64_t start_epoch,
+ uint64_t end_epoch)
+ {
+ return store->trim_usage(uid, start_epoch, end_epoch);
+ }