From: J. Eric Ivancich Date: Fri, 9 Feb 2024 03:46:37 +0000 (-0500) Subject: rgw: add new `object manifest` sub-command X-Git-Tag: v19.1.0~249^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3fcf1f42501cf383c35cd250a30e7d73f40a7cfb;p=ceph.git rgw: add new `object manifest` sub-command Adds a new sub-command to radosgw-admin to list the manifest, which are the rados objects that contain the RGW object's data. Signed-off-by: J. Eric Ivancich (cherry picked from commit cd068b831dc8cf665577db40563a2a6a03b6c4c0) --- diff --git a/doc/man/8/radosgw-admin.rst b/doc/man/8/radosgw-admin.rst index 778cef410293..dda2de57291b 100644 --- a/doc/man/8/radosgw-admin.rst +++ b/doc/man/8/radosgw-admin.rst @@ -140,6 +140,9 @@ as follows: :command:`object stat` Stat an object for its metadata. +:command:`object manifest` + Display the manifest of RADOS objects containing the data. + :command:`object unlink` Unlink object from bucket index. diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 8265852973f9..081204c24f44 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -682,6 +682,7 @@ enum class OPT { OBJECT_RM, OBJECT_UNLINK, OBJECT_STAT, + OBJECT_MANIFEST, OBJECT_REWRITE, OBJECT_REINDEX, OBJECTS_EXPIRE, @@ -903,6 +904,7 @@ static SimpleCmd::Commands all_cmds = { { "object rm", OPT::OBJECT_RM }, { "object unlink", OPT::OBJECT_UNLINK }, { "object stat", OPT::OBJECT_STAT }, + { "object manifest", OPT::OBJECT_MANIFEST }, { "object rewrite", OPT::OBJECT_REWRITE }, { "object reindex", OPT::OBJECT_REINDEX }, { "objects expire", OPT::OBJECTS_EXPIRE }, @@ -4180,6 +4182,7 @@ int main(int argc, const char **argv) OPT::LOG_SHOW, OPT::USAGE_SHOW, OPT::OBJECT_STAT, + OPT::OBJECT_MANIFEST, OPT::BI_GET, OPT::BI_LIST, OPT::OLH_GET, @@ -8327,7 +8330,7 @@ next: bufferlist& bl = iter->second; bool handled = false; if (iter->first == RGW_ATTR_MANIFEST) { - handled = decode_dump("manifest", bl, formatter.get()); + handled = decode_dump("manifest", bl, formatter.get()); } else if (iter->first == RGW_ATTR_ACL) { handled = decode_dump("policy", bl, formatter.get()); } else if (iter->first == RGW_ATTR_ID_TAG) { @@ -8360,7 +8363,76 @@ next: formatter->close_section(); formatter->close_section(); formatter->flush(cout); - } + } // OPT::OBJECT_STAT + + if (opt_cmd == OPT::OBJECT_MANIFEST) { + int ret = init_bucket(tenant, bucket_name, bucket_id, &bucket); + if (ret < 0) { + cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << + std::endl; + return -ret; + } + + std::unique_ptr obj = bucket->get_object(object); + obj->set_instance(object_version); + + ret = obj->get_obj_attrs(null_yield, dpp()); + if (ret < 0) { + cerr << "ERROR: failed to retrieve object metadata, returned error: " << + cpp_strerror(-ret) << std::endl; + return -ret; + } + + formatter->open_object_section("outer"); // name not displayed since top level + formatter->dump_unsigned("size", obj->get_obj_size()); + + auto attr_iter = obj->get_attrs().find(RGW_ATTR_MANIFEST); + if (attr_iter == obj->get_attrs().end()) { + cerr << "ERROR: unable to find object manifest" << std::endl; + return ENOENT; + } + + RGWObjManifest m; + try { + auto part_iter = attr_iter->second.cbegin(); + decode(m, part_iter); + } catch (buffer::error& err) { + cerr << "ERROR: unable to decode manifest" << std::endl; + return EIO; + } + + rgw::sal::RadosStore* store = + dynamic_cast(driver); + if (!store) { + cerr << "ERROR: this command (currently) only works with " + "RADOS back-ends" << std::endl; + return EINVAL; + } + + RGWRados* rados = store->getRados(); + + formatter->open_array_section("objects"); + unsigned index = 0; + for (auto p = m.obj_begin(dpp()); p != m.obj_end(dpp()); ++p, ++index) { + formatter->open_object_section("object"); // name not displayed since in array + + formatter->dump_unsigned("index", index); + formatter->dump_unsigned("part_id", p.get_cur_part_id()); + formatter->dump_unsigned("stripe_id", p.get_cur_stripe()); + formatter->dump_unsigned("offset", p.get_ofs()); + formatter->dump_unsigned("size", p.get_stripe_size()); + + formatter->open_object_section("raw_obj"); + p.get_location().get_raw_obj(rados).dump(formatter.get()); + formatter->close_section(); // raw_obj + + formatter->close_section(); // object + } + formatter->close_section(); // objects array + + formatter->close_section(); // outer + formatter->flush(cout); + } // OPT::OBJECT_MANIFEST if (opt_cmd == OPT::BUCKET_CHECK) { if (check_head_obj_locator) { diff --git a/src/rgw/rgw_obj_types.h b/src/rgw/rgw_obj_types.h index 70f9ddf5adf3..a092e5ccdab6 100644 --- a/src/rgw/rgw_obj_types.h +++ b/src/rgw/rgw_obj_types.h @@ -432,7 +432,7 @@ struct rgw_raw_obj { } void encode(bufferlist& bl) const { - ENCODE_START(6, 6, bl); + ENCODE_START(6, 6, bl); encode(pool, bl); encode(oid, bl); encode(loc, bl);