From 84d746b36007cb9a5504ac06e28ea9b7919e69c2 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Mon, 9 Mar 2015 19:33:07 +0100 Subject: [PATCH] rgw: split and refactor RGWPutMetadata classes. Signed-off-by: Radoslaw Zarzynski --- src/rgw/rgw_op.cc | 230 +++++++++++++++++++++++--------------- src/rgw/rgw_op.h | 66 +++++++++-- src/rgw/rgw_rest.h | 20 +++- src/rgw/rgw_rest_swift.cc | 132 +++++++++++++--------- src/rgw/rgw_rest_swift.h | 24 +++- 5 files changed, 321 insertions(+), 151 deletions(-) diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 4611357b0eeb..ba0f588727ba 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2034,129 +2034,182 @@ done: } -int RGWPutMetadata::verify_permission() +static void populate_with_generic_attrs(const req_state * const s, + map& out_attrs) { - const bool is_object_op = (!s->object.empty()); - const bool is_bucket_op = (!s->bucket_name_str.empty() && !is_object_op); + map::const_iterator giter; - if (is_object_op) { - if (!verify_object_permission(s, RGW_PERM_WRITE)) - return -EACCES; - } else if (is_bucket_op) { - if (!verify_bucket_permission(s, RGW_PERM_WRITE)) - return -EACCES; + for (giter = s->generic_attrs.begin(); giter != s->generic_attrs.end(); ++giter) { + bufferlist& attrbl = out_attrs[giter->first]; + const string& val = giter->second; + attrbl.clear(); + attrbl.append(val.c_str(), val.size() + 1); } - - return 0; } -void RGWPutMetadata::pre_exec() +static void prepare_add_del_attrs(const map& orig_attrs, + map& out_attrs, + map& out_rmattrs) { - const bool is_account_op = s->bucket_name_str.empty(); + map::const_iterator iter; - if (!is_account_op) { - rgw_bucket_object_pre_exec(s); + for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) { + const string& name = iter->first; + /* check if the attr is user-defined metadata item */ + if (name.compare(0, sizeof(RGW_ATTR_META_PREFIX) - 1, RGW_ATTR_META_PREFIX) == 0) { + /* for the objects all existing meta attrs have to be removed */ + out_rmattrs[name] = iter->second; + } else if (out_attrs.find(name) == out_attrs.end()) { + out_attrs[name] = iter->second; + } } } -void RGWPutMetadata::execute() +static void prepare_add_del_attrs(const map& orig_attrs, + const set& rmattr_names, + map& out_attrs, + map& out_rmattrs) { - const char *meta_prefix = RGW_ATTR_META_PREFIX; - int meta_prefix_len = sizeof(RGW_ATTR_META_PREFIX) - 1; - map attrs, orig_attrs, rmattrs; - map::iterator iter; - bufferlist bl, cors_bl; - rgw_obj obj; - RGWObjVersionTracker acct_ot; + map::const_iterator iter; - const bool is_object_op = (!s->object.empty()); - const bool is_bucket_op = (!s->bucket_name_str.empty() && !is_object_op); + for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) { + const string& name = iter->first; + /* check if the attr is user-defined metadata item */ + if (name.compare(0, strlen(RGW_ATTR_META_PREFIX), RGW_ATTR_META_PREFIX) == 0) { + /* for the buckets all existing meta attrs are preserved, + except those that are listed in rmattr_names. */ + if (rmattr_names.find(name) != rmattr_names.end()) { + map::iterator aiter = out_attrs.find(name); + if (aiter != out_attrs.end()) { + out_attrs.erase(aiter); + } + out_rmattrs[name] = iter->second; + } + } else if (out_attrs.find(name) == out_attrs.end()) { + out_attrs[name] = iter->second; + } + } +} - if (is_object_op || is_bucket_op) { - obj = rgw_obj(s->bucket, s->object); - } else { - string buckets_obj_id; - rgw_get_buckets_obj(s->user.user_id, buckets_obj_id); +int RGWPutMetadataAccount::verify_permission() +{ + /* FIXME: check perms! */ + return 0; +} - obj = rgw_obj(store->zone.user_uid_pool, buckets_obj_id); - } +void RGWPutMetadataAccount::execute() +{ + rgw_obj obj; + map attrs, orig_attrs, rmattrs; + RGWObjVersionTracker acct_op_tracker; - store->set_atomic(s->obj_ctx, obj); + /* Get the name of raw object which stores the metadata in its xattrs. */ + string buckets_obj_id; + rgw_get_buckets_obj(s->user.user_id, buckets_obj_id); + obj = rgw_obj(store->zone.user_uid_pool, buckets_obj_id); ret = get_params(); if (ret < 0) { return; } - RGWObjVersionTracker *ptracker = NULL; - - rgw_get_request_metadata(s->cct, s->info, attrs, is_object_op); + rgw_get_request_metadata(s->cct, s->info, attrs); + rgw_get_user_attrs_by_uid(store, s->user.user_id, orig_attrs, &acct_op_tracker); + prepare_add_del_attrs(orig_attrs, rmattr_names, attrs, rmattrs); + populate_with_generic_attrs(s, attrs); - if (is_object_op) { - /* check if obj exists, read orig attrs */ - ret = get_obj_attrs(store, s, obj, orig_attrs); - if (ret < 0) - return; - } else if (is_bucket_op) { - ptracker = &s->bucket_info.objv_tracker; - orig_attrs = s->bucket_attrs; + ret = rgw_store_user_attrs(store, s->user.user_id, attrs, &rmattrs, &acct_op_tracker); +} - if (!placement_rule.empty() && - placement_rule != s->bucket_info.placement_rule) { - ret = -EEXIST; - return; - } - } else { - ptracker = &acct_ot; - rgw_get_user_attrs_by_uid(store, s->user.user_id, orig_attrs, ptracker); +int RGWPutMetadataBucket::verify_permission() +{ + if (!verify_bucket_permission(s, RGW_PERM_WRITE)) { + return -EACCES; } - for (iter = orig_attrs.begin(); iter != orig_attrs.end(); ++iter) { - const string& name = iter->first; - /* check if the attr is user-defined metadata item */ - if (name.compare(0, meta_prefix_len, meta_prefix) == 0) { - if (is_object_op) { - /* for the objects all existing meta attrs have to be removed */ - rmattrs[name] = iter->second; - } else { - /* for the buckets all existing meta attrs are preserved, - except those that are listed in rmattr_names. */ - if (rmattr_names.find(name) != rmattr_names.end()) { - map::iterator aiter = attrs.find(name); - if (aiter != attrs.end()) { - attrs.erase(aiter); - } - rmattrs[name] = iter->second; - } - } - } else if (attrs.find(name) == attrs.end()) { - attrs[name] = iter->second; - } + return 0; +} + +void RGWPutMetadataBucket::pre_exec() +{ + rgw_bucket_object_pre_exec(s); +} + +void RGWPutMetadataBucket::execute() +{ + rgw_obj obj(s->bucket, s->object); + map attrs, orig_attrs, rmattrs; + + ret = get_params(); + if (ret < 0) { + return; } - map::iterator giter; - for (giter = s->generic_attrs.begin(); giter != s->generic_attrs.end(); ++giter) { - bufferlist& attrbl = attrs[giter->first]; - const string& val = giter->second; - attrbl.clear(); - attrbl.append(val.c_str(), val.size() + 1); + rgw_get_request_metadata(s->cct, s->info, attrs); + + if (!placement_rule.empty() && + placement_rule != s->bucket_info.placement_rule) { + ret = -EEXIST; + return; } + orig_attrs = s->bucket_attrs; + prepare_add_del_attrs(orig_attrs, rmattr_names, attrs, rmattrs); + populate_with_generic_attrs(s, attrs); + if (has_policy) { + bufferlist bl; policy.encode(bl); attrs[RGW_ATTR_ACL] = bl; } + if (has_cors) { - cors_config.encode(cors_bl); - attrs[RGW_ATTR_CORS] = cors_bl; + bufferlist bl; + cors_config.encode(bl); + attrs[RGW_ATTR_CORS] = bl; } - if (is_object_op) { - ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs, ptracker); - } else if (is_bucket_op) { - ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs, &rmattrs, ptracker); - } else { - ret = rgw_store_user_attrs(store, s->user.user_id, attrs, &rmattrs, ptracker); + + ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs, &rmattrs, + &s->bucket_info.objv_tracker); +} + +int RGWPutMetadataObject::verify_permission() +{ + if (!verify_object_permission(s, RGW_PERM_WRITE)) { + return -EACCES; + } + + return 0; +} + +void RGWPutMetadataObject::pre_exec() +{ + rgw_bucket_object_pre_exec(s); +} + +void RGWPutMetadataObject::execute() +{ + rgw_obj obj(s->bucket, s->object); + map attrs, orig_attrs, rmattrs; + + store->set_atomic(s->obj_ctx, obj); + + ret = get_params(); + if (ret < 0) { + return; } + + rgw_get_request_metadata(s->cct, s->info, attrs); + /* check if obj exists, read orig attrs */ + ret = get_obj_attrs(store, s, obj, orig_attrs); + if (ret < 0) { + return; + } + + /* Filter currently existing attributes. */ + prepare_add_del_attrs(orig_attrs, attrs, rmattrs); + populate_with_generic_attrs(s, attrs); + ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs, NULL); } int RGWSetTempUrl::verify_permission() @@ -2170,8 +2223,9 @@ int RGWSetTempUrl::verify_permission() void RGWSetTempUrl::execute() { ret = get_params(); - if (ret < 0) + if (ret < 0) { return; + } RGWUserAdminOpState user_op; user_op.set_user_id(s->user.user_id); diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 5c5a445757e3..45e322a5deac 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -44,7 +44,9 @@ enum RGWOpType { RGW_OP_DELETE_BUCKET, RGW_OP_PUT_OBJ, RGW_OP_POST_OBJ, - RGW_OP_PUT_METADATA, + RGW_OP_PUT_METADATA_ACCOUNT, + RGW_OP_PUT_METADATA_BUCKET, + RGW_OP_PUT_METADATA_OBJECT, RGW_OP_SET_TEMPURL, RGW_OP_DELETE_OBJ, RGW_OP_COPY_OBJ, @@ -508,7 +510,33 @@ public: virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; } }; -class RGWPutMetadata : public RGWOp { +class RGWPutMetadataAccount : public RGWOp { +protected: + int ret; + set rmattr_names; + RGWAccessControlPolicy policy; + +public: + RGWPutMetadataAccount() + : ret(0) + {} + + virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) { + RGWOp::init(store, s, h); + policy.set_ctx(s->cct); + } + int verify_permission(); + void pre_exec() { return; } + void execute(); + + virtual int get_params() = 0; + virtual void send_response() = 0; + virtual const string name() { return "put_account_metadata"; } + virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA_ACCOUNT; } + virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; } +}; + +class RGWPutMetadataBucket : public RGWOp { protected: int ret; set rmattr_names; @@ -518,11 +546,35 @@ protected: string placement_rule; public: - RGWPutMetadata() { - has_cors = false; - has_policy = false; - ret = 0; + RGWPutMetadataBucket() + : ret(0), has_policy(false), has_cors(false) + {} + + virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) { + RGWOp::init(store, s, h); + policy.set_ctx(s->cct); } + int verify_permission(); + void pre_exec(); + void execute(); + + virtual int get_params() = 0; + virtual void send_response() = 0; + virtual const string name() { return "put_bucket_metadata"; } + virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA_BUCKET; } + virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; } +}; + +class RGWPutMetadataObject : public RGWOp { +protected: + int ret; + RGWAccessControlPolicy policy; + string placement_rule; + +public: + RGWPutMetadataObject() + : ret(0) + {} virtual void init(RGWRados *store, struct req_state *s, RGWHandler *h) { RGWOp::init(store, s, h); @@ -535,7 +587,7 @@ public: virtual int get_params() = 0; virtual void send_response() = 0; virtual const string name() { return "put_obj_metadata"; } - virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA; } + virtual RGWOpType get_type() { return RGW_OP_PUT_METADATA_OBJECT; } virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; } }; diff --git a/src/rgw/rgw_rest.h b/src/rgw/rgw_rest.h index a6b680b2e846..5b707b62abbc 100644 --- a/src/rgw/rgw_rest.h +++ b/src/rgw/rgw_rest.h @@ -163,11 +163,25 @@ public: virtual int verify_params(); }; -class RGWPutMetadata_ObjStore : public RGWPutMetadata +class RGWPutMetadataAccount_ObjStore : public RGWPutMetadataAccount { public: - RGWPutMetadata_ObjStore() {} - ~RGWPutMetadata_ObjStore() {} + RGWPutMetadataAccount_ObjStore() {} + ~RGWPutMetadataAccount_ObjStore() {} +}; + +class RGWPutMetadataBucket_ObjStore : public RGWPutMetadataBucket +{ +public: + RGWPutMetadataBucket_ObjStore() {} + ~RGWPutMetadataBucket_ObjStore() {} +}; + +class RGWPutMetadataObject_ObjStore : public RGWPutMetadataObject +{ +public: + RGWPutMetadataObject_ObjStore() {} + ~RGWPutMetadataObject_ObjStore() {} }; class RGWSetTempUrl_ObjStore : public RGWSetTempUrl { diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 2a86eaeb377a..546a281cb792 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -497,73 +497,105 @@ void RGWPutObj_ObjStore_SWIFT::send_response() #define CONT_REMOVE_ATTR_PREFIX "HTTP_X_REMOVE_CONTAINER_META_" #define CONT_PUT_ATTR_PREFIX "HTTP_X_CONTAINER_META_" -int RGWPutMetadata_ObjStore_SWIFT::get_params() +static void get_rmattrs_from_headers(const req_state * const s, + const char * const put_prefix, + const char * const del_prefix, + set& rmattr_names) { - if (s->has_bad_meta) + map& m = s->info.env->get_map(); + map::const_iterator iter; + const size_t put_prefix_len = strlen(put_prefix); + const size_t del_prefix_len = strlen(del_prefix); + + for (iter = m.begin(); iter != m.end(); ++iter) { + size_t prefix_len = 0; + const char * const p = iter->first.c_str(); + + if (strncasecmp(p, del_prefix, del_prefix_len) == 0) { + /* Explicitly requested removal. */ + prefix_len = del_prefix_len; + } else if ((strncasecmp(p, put_prefix, put_prefix_len) == 0) + && iter->second.empty()) { + /* Removal requested by putting an empty value. */ + prefix_len = put_prefix_len; + } + + if (prefix_len > 0) { + string name(RGW_ATTR_META_PREFIX); + name.append(lowercase_dash_http_attr(p + prefix_len)); + rmattr_names.insert(name); + } + } +} + +int RGWPutMetadataAccount_ObjStore_SWIFT::get_params() +{ + if (s->has_bad_meta) { return -EINVAL; + } - const bool is_bucket_op = (!s->bucket_name_str.empty() && s->object.empty()); - const bool is_account_op = (s->bucket_name_str.empty()); + get_rmattrs_from_headers(s, ACCT_PUT_ATTR_PREFIX, ACCT_REMOVE_ATTR_PREFIX, rmattr_names); + return 0; +} - const char *put_attr_prefix; - const char *del_attr_prefix; - if (is_bucket_op) { - put_attr_prefix = CONT_PUT_ATTR_PREFIX; - del_attr_prefix = CONT_REMOVE_ATTR_PREFIX; - } else { - put_attr_prefix = ACCT_PUT_ATTR_PREFIX; - del_attr_prefix = ACCT_REMOVE_ATTR_PREFIX; +void RGWPutMetadataAccount_ObjStore_SWIFT::send_response() +{ + if (!ret) { + /* FIXME: check the proper HTTP return code. */ + ret = STATUS_NO_CONTENT; } + set_req_state_err(s, ret); + dump_errno(s); + end_header(s, this); + rgw_flush_formatter_and_reset(s, s->formatter); +} - const size_t put_attr_prefix_len = strlen(put_attr_prefix); - const size_t del_attr_prefix_len = strlen(del_attr_prefix); - if (is_bucket_op) { - int r = get_swift_container_settings(s, store, &policy, &has_policy, &cors_config, &has_cors); - if (r < 0) { - return r; - } +int RGWPutMetadataBucket_ObjStore_SWIFT::get_params() +{ + if (s->has_bad_meta) { + return -EINVAL; } - if (is_bucket_op || is_account_op) { - map& m = s->info.env->get_map(); - map::iterator iter; - for (iter = m.begin(); iter != m.end(); ++iter) { - size_t prefix_len = 0; - const char *p = iter->first.c_str(); - if (strncasecmp(p, del_attr_prefix, del_attr_prefix_len) == 0) { - // Explicitly requested removal - prefix_len = del_attr_prefix_len; - } else if ((strncasecmp(p, put_attr_prefix, put_attr_prefix_len) == 0) && iter->second.empty()) { - // Removal requested by putting an empty value - prefix_len = put_attr_prefix_len; - } - if (prefix_len > 0) { - string name(RGW_ATTR_META_PREFIX); - name.append(lowercase_dash_http_attr(p + prefix_len)); - rmattr_names.insert(name); - } - } + int r = get_swift_container_settings(s, store, &policy, &has_policy, &cors_config, &has_cors); + if (r < 0) { + return r; + } + + get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX, CONT_REMOVE_ATTR_PREFIX, rmattr_names); + placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", ""); + return 0; +} + +void RGWPutMetadataBucket_ObjStore_SWIFT::send_response() +{ + if (!ret) { + ret = STATUS_NO_CONTENT; } + set_req_state_err(s, ret); + dump_errno(s); + end_header(s, this); + rgw_flush_formatter_and_reset(s, s->formatter); +} - if (!is_account_op) { - placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", ""); +int RGWPutMetadataObject_ObjStore_SWIFT::get_params() +{ + if (s->has_bad_meta) { + return -EINVAL; } + placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", ""); return 0; } -void RGWPutMetadata_ObjStore_SWIFT::send_response() +void RGWPutMetadataObject_ObjStore_SWIFT::send_response() { if (!ret) { - /* Return 204 when post metadata on a container */ - if (s->object.empty()) - ret = STATUS_NO_CONTENT; - else - ret = STATUS_ACCEPTED; + ret = STATUS_ACCEPTED; } set_req_state_err(s, ret); - if (!s->err.is_err()) + if (!s->err.is_err()) { dump_content_length(s, 0); + } dump_errno(s); end_header(s, this); rgw_flush_formatter_and_reset(s, s->formatter); @@ -782,7 +814,7 @@ RGWOp *RGWHandler_ObjStore_Service_SWIFT::op_post() if (temp_url) { return new RGWSetTempUrl_ObjStore_SWIFT; } - return new RGWPutMetadata_ObjStore_SWIFT; + return new RGWPutMetadataAccount_ObjStore_SWIFT; } RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::get_obj_op(bool get_data) @@ -828,7 +860,7 @@ RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_delete() RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_post() { - return new RGWPutMetadata_ObjStore_SWIFT; + return new RGWPutMetadataBucket_ObjStore_SWIFT; } RGWOp *RGWHandler_ObjStore_Bucket_SWIFT::op_options() @@ -881,7 +913,7 @@ RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_delete() RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_post() { - return new RGWPutMetadata_ObjStore_SWIFT; + return new RGWPutMetadataObject_ObjStore_SWIFT; } RGWOp *RGWHandler_ObjStore_Obj_SWIFT::op_copy() diff --git a/src/rgw/rgw_rest_swift.h b/src/rgw/rgw_rest_swift.h index bf9dfcdc4eac..7fae8d03eb76 100644 --- a/src/rgw/rgw_rest_swift.h +++ b/src/rgw/rgw_rest_swift.h @@ -89,10 +89,28 @@ public: void send_response(); }; -class RGWPutMetadata_ObjStore_SWIFT : public RGWPutMetadata_ObjStore { +class RGWPutMetadataAccount_ObjStore_SWIFT : public RGWPutMetadataAccount_ObjStore { public: - RGWPutMetadata_ObjStore_SWIFT() {} - ~RGWPutMetadata_ObjStore_SWIFT() {} + RGWPutMetadataAccount_ObjStore_SWIFT() {} + ~RGWPutMetadataAccount_ObjStore_SWIFT() {} + + int get_params(); + void send_response(); +}; + +class RGWPutMetadataBucket_ObjStore_SWIFT : public RGWPutMetadataBucket_ObjStore { +public: + RGWPutMetadataBucket_ObjStore_SWIFT() {} + ~RGWPutMetadataBucket_ObjStore_SWIFT() {} + + int get_params(); + void send_response(); +}; + +class RGWPutMetadataObject_ObjStore_SWIFT : public RGWPutMetadataObject_ObjStore { +public: + RGWPutMetadataObject_ObjStore_SWIFT() {} + ~RGWPutMetadataObject_ObjStore_SWIFT() {} int get_params(); void send_response(); -- 2.47.3