From: Radoslaw Zarzynski Date: Mon, 9 Nov 2015 16:16:34 +0000 (+0100) Subject: rgw: add support for multipart delete on a SLO of Swift. X-Git-Tag: v10.0.2~36^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7e06dba6ba84909adf17618db4a00b4c06e0ee50;p=ceph.git rgw: add support for multipart delete on a SLO of Swift. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 89115b2dd8f..998b2ba2fdb 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -152,6 +152,7 @@ using ceph::crypto::MD5; #define ERR_INVALID_ACCESS_KEY 2028 #define ERR_MALFORMED_XML 2029 #define ERR_USER_EXIST 2030 +#define ERR_NOT_SLO_MANIFEST 2031 #define ERR_USER_SUSPENDED 2100 #define ERR_INTERNAL_ERROR 2200 #define ERR_NOT_IMPLEMENTED 2201 diff --git a/src/rgw/rgw_http_errors.h b/src/rgw/rgw_http_errors.h index aaa5312cbec..7750d136c8e 100644 --- a/src/rgw/rgw_http_errors.h +++ b/src/rgw/rgw_http_errors.h @@ -66,6 +66,7 @@ const static struct rgw_http_errors RGW_HTTP_SWIFT_ERRORS[] = { { ERR_USER_SUSPENDED, 401, "UserSuspended" }, { ERR_INVALID_UTF8, 412, "Invalid UTF8" }, { ERR_BAD_URL, 412, "Bad URL" }, + { ERR_NOT_SLO_MANIFEST, 400, "Not an SLO manifest" } }; struct rgw_http_status_code { diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 19608a3ab7c..79093f775b4 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2659,6 +2659,61 @@ void RGWPutMetadataObject::execute() ret = store->set_attrs(s->obj_ctx, obj, attrs, &rmattrs, NULL); } +int RGWDeleteObj::handle_slo_manifest(bufferlist& bl) +{ + RGWSLOInfo slo_info; + bufferlist::iterator bliter = bl.begin(); + try { + ::decode(slo_info, bliter); + } catch (buffer::error& err) { + ldout(s->cct, 0) << "ERROR: failed to decode slo manifest" << dendl; + return -EIO; + } + + try { + deleter = std::unique_ptr(\ + new RGWBulkDelete::Deleter(store, s)); + } catch (std::bad_alloc) { + return -ENOMEM; + } + + list items; + for (const auto& iter : slo_info.entries) { + const string& path_str = iter.path; + + const size_t sep_pos = path_str.find('/', 1 /* skip first slash */); + if (string::npos == sep_pos) { + return -EINVAL; + } + + RGWBulkDelete::acct_path_t path; + + string bucket_name; + url_decode(path_str.substr(1, sep_pos - 1), bucket_name); + + string obj_name; + url_decode(path_str.substr(sep_pos + 1), obj_name); + + path.bucket_name = bucket_name; + path.obj_key = obj_name; + + items.push_back(path); + } + + /* Request removal of the manifet object itself. */ + RGWBulkDelete::acct_path_t path; + path.bucket_name = s->bucket_name_str; + path.obj_key = s->object; + items.push_back(path); + + int ret = deleter->delete_chunk(items); + if (ret < 0) { + return ret; + } + + return 0; +} + int RGWDeleteObj::verify_permission() { if (!verify_bucket_permission(s, RGW_PERM_WRITE)) @@ -2676,16 +2731,37 @@ void RGWDeleteObj::execute() { ret = -EINVAL; rgw_obj obj(s->bucket, s->object); - map orig_attrs; + map attrs; + + ret = get_params(); + if (ret < 0) { + return; + } if (!s->object.empty()) { - if (need_object_expiration()) { + if (need_object_expiration() || multipart_delete) { /* check if obj exists, read orig attrs */ - ret = get_obj_attrs(store, s, obj, orig_attrs); + ret = get_obj_attrs(store, s, obj, attrs); if (ret < 0) { return; } } + + if (multipart_delete) { + const auto slo_attr = attrs.find(RGW_ATTR_SLO_MANIFEST); + + if (slo_attr != attrs.end()) { + ret = handle_slo_manifest(slo_attr->second); + if (ret < 0) { + ldout(s->cct, 0) << "ERROR: failed to handle slo manifest ret=" << ret << dendl; + } + } else { + ret = -ERR_NOT_SLO_MANIFEST; + } + + return; + } + RGWObjectCtx *obj_ctx = static_cast(s->obj_ctx); obj_ctx->set_atomic(obj); @@ -2697,6 +2773,7 @@ void RGWDeleteObj::execute() if (ret < 0) { return; } + del_op.params.bucket_owner = s->bucket_owner.get_id(); del_op.params.versioning_status = s->bucket_info.versioning_status(); del_op.params.obj_owner = s->owner; @@ -2709,7 +2786,7 @@ void RGWDeleteObj::execute() /* Check whether the object has expired. Swift API documentation * stands that we should return 404 Not Found in such case. */ - if (need_object_expiration() && object_is_expired(orig_attrs)) { + if (need_object_expiration() && object_is_expired(attrs)) { ret = -ENOENT; return; } diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index ce0f70d21d8..3c3d873fa90 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -764,15 +764,24 @@ class RGWDeleteObj : public RGWOp { protected: int ret; bool delete_marker; + bool multipart_delete; string version_id; + std::unique_ptr deleter; public: - RGWDeleteObj() : ret(0), delete_marker(false) {} + RGWDeleteObj() + : ret(0), + delete_marker(false), + multipart_delete(false), + deleter(nullptr) { + } int verify_permission(); void pre_exec(); void execute(); + int handle_slo_manifest(bufferlist& bl); + virtual int get_params() { return 0; }; virtual void send_response() = 0; virtual const string name() { return "delete_obj"; } virtual RGWOpType get_type() { return RGW_OP_DELETE_OBJ; } diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 0ca9ce9996c..8f17c103b23 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -731,6 +731,14 @@ void RGWPutMetadataObject_ObjStore_SWIFT::send_response() rgw_flush_formatter_and_reset(s, s->formatter); } +int RGWDeleteObj_ObjStore_SWIFT::get_params() +{ + const string& mm = s->info.args.get("multipart-manifest"); + multipart_delete = (mm.compare("delete") == 0); + + return RGWDeleteObj_ObjStore::get_params(); +} + void RGWDeleteObj_ObjStore_SWIFT::send_response() { int r = ret; diff --git a/src/rgw/rgw_rest_swift.h b/src/rgw/rgw_rest_swift.h index 7647cb12555..a64c9966d99 100644 --- a/src/rgw/rgw_rest_swift.h +++ b/src/rgw/rgw_rest_swift.h @@ -125,6 +125,7 @@ public: RGWDeleteObj_ObjStore_SWIFT() {} ~RGWDeleteObj_ObjStore_SWIFT() {} + int get_params(); bool need_object_expiration() { return true; } void send_response(); };