From: Cory Snyder Date: Fri, 15 Jul 2022 02:51:48 +0000 (-0400) Subject: rgw: log deletion status of individual objects in multi object delete request X-Git-Tag: v18.1.0~1085^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fbd2858b610e552253fd35c80c5d52c1d7b1bfa5;p=ceph.git rgw: log deletion status of individual objects in multi object delete request Provides ops log visibility for individual objects that are deleted as part of a multi-object delete request. Fixes: https://tracker.ceph.com/issues/56645 Signed-off-by: Cory Snyder --- diff --git a/src/rgw/rgw_log.cc b/src/rgw/rgw_log.cc index 2618a8845c7..bb85b90e5a3 100644 --- a/src/rgw/rgw_log.cc +++ b/src/rgw/rgw_log.cc @@ -323,6 +323,29 @@ void rgw_format_ops_log_entry(struct rgw_log_entry& entry, Formatter *formatter) formatter->dump_string("subuser", entry.subuser); } formatter->dump_bool("temp_url", entry.temp_url); + + if (entry.op == "multi_object_delete") { + formatter->open_object_section("op_data"); + formatter->dump_bool("num_ok", entry.delete_multi_obj_meta.num_ok); + formatter->dump_bool("num_err", entry.delete_multi_obj_meta.num_err); + formatter->open_array_section("objects"); + for (const auto& iter: entry.delete_multi_obj_meta.objects) { + formatter->open_object_section(""); + formatter->dump_string("key", iter.key); + formatter->dump_string("version_id", iter.version_id); + formatter->dump_int("http_status", iter.http_status); + formatter->dump_bool("error", iter.error); + if (iter.error) { + formatter->dump_string("error_message", iter.error_message); + } else { + formatter->dump_bool("delete_marker", iter.delete_marker); + formatter->dump_string("marker_version_id", iter.marker_version_id); + } + formatter->close_section(); + } + formatter->close_section(); + formatter->close_section(); + } formatter->close_section(); } diff --git a/src/rgw/rgw_log.h b/src/rgw/rgw_log.h index 8acb433489a..154704b1943 100644 --- a/src/rgw/rgw_log.h +++ b/src/rgw/rgw_log.h @@ -13,6 +13,59 @@ class RGWOp; +struct delete_multi_obj_entry { + std::string key, version_id, error_message, marker_version_id; + uint32_t http_status; + bool error, delete_marker; + + void encode(bufferlist &bl) const { + ENCODE_START(1, 1, bl); + encode(key, bl); + encode(version_id, bl); + encode(error_message, bl); + encode(marker_version_id, bl); + encode(http_status, bl); + encode(error, bl); + encode(delete_marker, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator &p) { + DECODE_START_LEGACY_COMPAT_LEN(1, 1, 1, p); + decode(key, p); + decode(version_id, p); + decode(error_message, p); + decode(marker_version_id, p); + decode(http_status, p); + decode(error, p); + decode(delete_marker, p); + DECODE_FINISH(p); + } +}; +WRITE_CLASS_ENCODER(delete_multi_obj_entry) + +struct delete_multi_obj_op_meta { + uint32_t num_ok, num_err; + std::vector objects; + + void encode(bufferlist &bl) const { + ENCODE_START(1, 1, bl); + encode(num_ok, bl); + encode(num_err, bl); + encode(objects, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::const_iterator &p) { + DECODE_START_LEGACY_COMPAT_LEN(1, 1, 1, p); + decode(num_ok, p); + decode(num_err, p); + decode(objects, p); + DECODE_FINISH(p); + } +}; +WRITE_CLASS_ENCODER(delete_multi_obj_op_meta) + struct rgw_log_entry { using headers_map = boost::container::flat_map; @@ -43,9 +96,10 @@ struct rgw_log_entry { std::string access_key_id; std::string subuser; bool temp_url {false}; + delete_multi_obj_op_meta delete_multi_obj_meta; void encode(bufferlist &bl) const { - ENCODE_START(13, 5, bl); + ENCODE_START(14, 5, bl); encode(object_owner.id, bl); encode(bucket_owner.id, bl); encode(bucket, bl); @@ -74,10 +128,11 @@ struct rgw_log_entry { encode(access_key_id, bl); encode(subuser, bl); encode(temp_url, bl); + encode(delete_multi_obj_meta, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator &p) { - DECODE_START_LEGACY_COMPAT_LEN(13, 5, 5, p); + DECODE_START_LEGACY_COMPAT_LEN(14, 5, 5, p); decode(object_owner.id, p); if (struct_v > 3) decode(bucket_owner.id, p); @@ -137,6 +192,9 @@ struct rgw_log_entry { decode(subuser, p); decode(temp_url, p); } + if (struct_v >= 14) { + decode(delete_multi_obj_meta, p); + } DECODE_FINISH(p); } void dump(ceph::Formatter *f) const; diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 84e79492c0e..4ccd2ceb625 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -6818,6 +6818,23 @@ void RGWDeleteMultiObj::pre_exec() rgw_bucket_object_pre_exec(s); } +void RGWDeleteMultiObj::write_ops_log_entry(rgw_log_entry& entry) const { + int num_err = 0; + int num_ok = 0; + for (auto iter = ops_log_entries.begin(); + iter != ops_log_entries.end(); + ++iter) { + if (iter->error) { + num_err++; + } else { + num_ok++; + } + } + entry.delete_multi_obj_meta.num_err = num_err; + entry.delete_multi_obj_meta.num_ok = num_ok; + entry.delete_multi_obj_meta.objects = std::move(ops_log_entries); +} + void RGWDeleteMultiObj::execute(optional_yield y) { RGWMultiDelDelete *multi_delete; diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index e6db5862e71..bfcda73b43b 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -44,6 +44,7 @@ #include "rgw_putobj.h" #include "rgw_sal.h" #include "rgw_compression_types.h" +#include "rgw_log.h" #include "rgw_lc.h" #include "rgw_torrent.h" @@ -2029,6 +2030,7 @@ public: class RGWDeleteMultiObj : public RGWOp { protected: + std::vector ops_log_entries; bufferlist data; rgw::sal::Bucket* bucket; bool quiet; @@ -2058,6 +2060,8 @@ public: const char* name() const override { return "multi_object_delete"; } RGWOpType get_type() override { return RGW_OP_DELETE_MULTI_OBJ; } uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; } + + void write_ops_log_entry(rgw_log_entry& entry) const override; }; class RGWInfo: public RGWOp { diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index dcb9edec809..4de7f604e14 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -4143,17 +4143,28 @@ void RGWDeleteMultiObj_ObjStore_S3::send_partial_response(rgw_obj_key& key, const string& marker_version_id, int ret) { if (!key.empty()) { - if (ret == 0 && !quiet) { - s->formatter->open_object_section("Deleted"); - s->formatter->dump_string("Key", key.name); - if (!key.instance.empty()) { - s->formatter->dump_string("VersionId", key.instance); - } + delete_multi_obj_entry ops_log_entry; + ops_log_entry.key = key.name; + ops_log_entry.version_id = key.instance; + if (ret == 0) { + ops_log_entry.error = false; + ops_log_entry.http_status = 200; + ops_log_entry.delete_marker = delete_marker; if (delete_marker) { - s->formatter->dump_bool("DeleteMarker", true); - s->formatter->dump_string("DeleteMarkerVersionId", marker_version_id); + ops_log_entry.marker_version_id = marker_version_id; + } + if (!quiet) { + s->formatter->open_object_section("Deleted"); + s->formatter->dump_string("Key", key.name); + if (!key.instance.empty()) { + s->formatter->dump_string("VersionId", key.instance); + } + if (delete_marker) { + s->formatter->dump_bool("DeleteMarker", true); + s->formatter->dump_string("DeleteMarkerVersionId", marker_version_id); + } + s->formatter->close_section(); } - s->formatter->close_section(); } else if (ret < 0) { struct rgw_http_error r; int err_no; @@ -4163,6 +4174,10 @@ void RGWDeleteMultiObj_ObjStore_S3::send_partial_response(rgw_obj_key& key, err_no = -ret; rgw_get_errno_s3(&r, err_no); + ops_log_entry.error = true; + ops_log_entry.http_status = r.http_ret; + ops_log_entry.error_message = r.s3_code; + s->formatter->dump_string("Key", key.name); s->formatter->dump_string("VersionId", key.instance); s->formatter->dump_string("Code", r.s3_code); @@ -4170,6 +4185,7 @@ void RGWDeleteMultiObj_ObjStore_S3::send_partial_response(rgw_obj_key& key, s->formatter->close_section(); } + ops_log_entries.push_back(std::move(ops_log_entry)); rgw_flush_formatter(s, s->formatter); } } diff --git a/src/test/rgw/test_rgw_lua.cc b/src/test/rgw/test_rgw_lua.cc index 41c3c7fdd53..91c01c19b7d 100644 --- a/src/test/rgw/test_rgw_lua.cc +++ b/src/test/rgw/test_rgw_lua.cc @@ -358,7 +358,7 @@ TEST(TestRGWLua, WriteBucket) DEFINE_REQ_STATE; s.init_state.url_bucket = "myname"; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); ASSERT_EQ(rc, 0); ASSERT_EQ(s.init_state.url_bucket, "othername"); } @@ -376,7 +376,7 @@ TEST(TestRGWLua, WriteBucketFail) b.name = "myname"; s.bucket.reset(new sal::RadosBucket(nullptr, b)); - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); ASSERT_NE(rc, 0); } @@ -551,7 +551,7 @@ TEST(TestRGWLua, User) u.id = "myid"; s.user.reset(new sal::RadosUser(nullptr, u)); - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); ASSERT_EQ(rc, 0); } @@ -778,7 +778,7 @@ TEST(TestRGWLuaBackground, RequestScript) // to make sure test is consistent we have to puase the background lua_background.pause(); - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "hello"), "from request"); // now we resume and let the background set the value @@ -927,7 +927,7 @@ TEST(TestRGWLuaBackground, TableValues) DEFINE_REQ_STATE; s.lua_background = &lua_background; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), "string value"); EXPECT_EQ(get_table_value(lua_background, "key2"), 42); @@ -948,7 +948,7 @@ TEST(TestRGWLuaBackground, TablePersist) DEFINE_REQ_STATE; s.lua_background = &lua_background; - auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), "string value"); EXPECT_EQ(get_table_value(lua_background, "key2"), 42); @@ -958,7 +958,7 @@ TEST(TestRGWLuaBackground, TablePersist) RGW["key4"] = RGW["key2"] )"; - rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), "string value"); EXPECT_EQ(get_table_value(lua_background, "key2"), 42); @@ -987,7 +987,7 @@ TEST(TestRGWLuaBackground, TableValuesFromRequest) s.err.ret = -99; s.err.message = "hi"; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), -99); EXPECT_EQ(get_table_value(lua_background, "key2"), "hi"); @@ -1014,7 +1014,7 @@ TEST(TestRGWLuaBackground, TableInvalidValue) s.tagset.add_tag("key1", "val1"); s.tagset.add_tag("key2", "val2"); - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_NE(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), "val1"); EXPECT_EQ(get_table_value(lua_background, "key2"), 42); @@ -1038,7 +1038,7 @@ TEST(TestRGWLuaBackground, TableErase) DEFINE_REQ_STATE; s.lua_background = &lua_background; - auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), "string value"); EXPECT_EQ(get_table_value(lua_background, "key2"), 42); @@ -1053,7 +1053,7 @@ TEST(TestRGWLuaBackground, TableErase) RGW["size"] = #RGW )"; - rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), ""); EXPECT_EQ(get_table_value(lua_background, "key2"), 42); @@ -1080,7 +1080,7 @@ TEST(TestRGWLuaBackground, TableIterate) DEFINE_REQ_STATE; s.lua_background = &lua_background; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); EXPECT_EQ(get_table_value(lua_background, "key1"), "string value"); EXPECT_EQ(get_table_value(lua_background, "key2"), 42); @@ -1106,7 +1106,7 @@ TEST(TestRGWLuaBackground, TableIncrement) DEFINE_REQ_STATE; s.lua_background = &lua_background; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); } @@ -1129,7 +1129,7 @@ TEST(TestRGWLuaBackground, TableIncrementBy) DEFINE_REQ_STATE; s.lua_background = &lua_background; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); } @@ -1150,7 +1150,7 @@ TEST(TestRGWLuaBackground, TableDecrement) DEFINE_REQ_STATE; s.lua_background = &lua_background; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); } @@ -1173,7 +1173,7 @@ TEST(TestRGWLuaBackground, TableDecrementBy) DEFINE_REQ_STATE; s.lua_background = &lua_background; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_EQ(rc, 0); } @@ -1191,7 +1191,7 @@ TEST(TestRGWLuaBackground, TableIncrementValueError) DEFINE_REQ_STATE; s.lua_background = &lua_background; - auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_NE(rc, 0); request_script = R"( @@ -1200,7 +1200,7 @@ TEST(TestRGWLuaBackground, TableIncrementValueError) RGW.increment("key1") )"; - rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_NE(rc, 0); request_script = R"( @@ -1209,7 +1209,7 @@ TEST(TestRGWLuaBackground, TableIncrementValueError) RGW.increment("key1", "kaboom") )"; - rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_NE(rc, 0); } @@ -1227,7 +1227,7 @@ TEST(TestRGWLuaBackground, TableIncrementError) DEFINE_REQ_STATE; s.lua_background = &lua_background; - auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_NE(rc, 0); request_script = R"( @@ -1235,7 +1235,7 @@ TEST(TestRGWLuaBackground, TableIncrementError) RGW.increment = 11 )"; - rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "", request_script); + rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, request_script); ASSERT_NE(rc, 0); } @@ -1249,7 +1249,7 @@ TEST(TestRGWLua, TracingSetAttribute) DEFINE_REQ_STATE; INIT_TRACE; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); ASSERT_EQ(rc, 0); } @@ -1261,7 +1261,7 @@ TEST(TestRGWLua, TracingSetBadAttribute) DEFINE_REQ_STATE; INIT_TRACE; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); #ifdef HAVE_JAEGER ASSERT_NE(rc, 0); #else @@ -1283,7 +1283,7 @@ TEST(TestRGWLua, TracingAddEvent) DEFINE_REQ_STATE; INIT_TRACE; - const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, "put_obj", script); + const auto rc = lua::request::execute(nullptr, nullptr, nullptr, &s, nullptr, script); ASSERT_EQ(rc, 0); }