]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add new `object manifest` sub-command
authorJ. Eric Ivancich <ivancich@redhat.com>
Fri, 9 Feb 2024 03:46:37 +0000 (22:46 -0500)
committerJ. Eric Ivancich <ivancich@redhat.com>
Thu, 29 Feb 2024 14:45:55 +0000 (09:45 -0500)
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 <ivancich@redhat.com>
(cherry picked from commit cd068b831dc8cf665577db40563a2a6a03b6c4c0)

doc/man/8/radosgw-admin.rst
src/rgw/rgw_admin.cc
src/rgw/rgw_obj_types.h

index 778cef410293bb238f2374b195cb2de73468ed35..dda2de57291b51a24cb1d429d8a9f8ada07960aa 100644 (file)
@@ -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.
 
index 8265852973f905716badf580c519d9ffe34453c6..081204c24f4474abcb7f058cb32f5f77d22ffd86 100644 (file)
@@ -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<RGWObjManifest>("manifest", bl, formatter.get());
+       handled = decode_dump<RGWObjManifest>("manifest", bl, formatter.get());
       } else if (iter->first == RGW_ATTR_ACL) {
         handled = decode_dump<RGWAccessControlPolicy>("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<rgw::sal::Object> 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<rgw::sal::RadosStore*>(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) {
index 70f9ddf5adf30c970ddb725f29918dea746e45db..a092e5ccdab69f498834a0a2aaf405d00aa680e3 100644 (file)
@@ -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);