]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
src/rgw_bucket.cc: include restore stats in the same json dict for bucket stats
authorJiffin Tony Thottan <thottanjiffin@gmail.com>
Fri, 17 Oct 2025 09:00:24 +0000 (14:30 +0530)
committerJiffin Tony Thottan <thottanjiffin@gmail.com>
Wed, 5 Nov 2025 06:25:15 +0000 (11:55 +0530)
Resolves: rhbz#2403699

Signed-off-by: Jiffin Tony Thottan <thottanjiffin@gmail.com>
(cherry picked from commit 1085dfca361fc880c14542ea49094753e303ffc8)

src/rgw/driver/rados/rgw_bucket.cc
src/rgw/driver/rados/rgw_rest_bucket.cc
src/rgw/radosgw-admin/radosgw-admin.cc
src/test/cli/radosgw-admin/help.t

index 1f45b37f2c69484bc996d2ae76f1740e3893770b..7f187c70faa50cfa8f7c48f37faf326108720840 100644 (file)
@@ -1510,11 +1510,72 @@ int RGWBucketAdminOp::sync_bucket(rgw::sal::Driver* driver, RGWBucketAdminOpStat
   return bucket.sync(op_state, dpp, y, err_msg);
 }
 
-static int bucket_stats(rgw::sal::Driver* driver,
+static int bucket_restore_stats(rgw::sal::Driver* driver,
                         const std::string& tenant_name,
                         const std::string& bucket_name, Formatter* formatter,
                         const DoutPrefixProvider* dpp, optional_yield y) {
   std::unique_ptr<rgw::sal::Bucket> bucket;
+  int restore_completed_count = 0;
+  int restore_in_progress_count = 0;
+  int restore_failed_count = 0;
+  int ret = driver->load_bucket(dpp, rgw_bucket(tenant_name, bucket_name),
+                                &bucket, y);
+  if (ret < 0) {
+    return ret;
+  }
+  rgw::sal::Bucket::ListParams params;
+  rgw::sal::Bucket::ListResults results;
+  params.list_versions = bucket->versioned();
+  params.allow_unordered = true;
+  do {
+    ret = bucket->list(dpp, params, listing_max_entries, results, null_yield);
+    if (ret < 0) {
+      cerr << "ERROR: driver->list_objects(): " << cpp_strerror(-ret) << std::endl;
+      return ret;
+    }
+    for (vector<rgw_bucket_dir_entry>::iterator iter = results.objs.begin(); iter != results.objs.end(); ++iter) {
+      std::unique_ptr<rgw::sal::Object> obj = bucket->get_object(iter->key.name);
+      if (obj) {
+        ret = obj->get_obj_attrs(null_yield, dpp);
+        if (ret < 0) {
+          cerr << "ERROR: failed to stat object, returned error: " << cpp_strerror(-ret) << std::endl;
+          return ret;
+        }
+        for (map<string, bufferlist>::iterator getattriter = obj->get_attrs().begin(); getattriter != obj->get_attrs().end(); ++getattriter) {
+          bufferlist& bl = getattriter->second;
+          if (getattriter->first == RGW_ATTR_RESTORE_STATUS) {
+            rgw::sal::RGWRestoreStatus rs;
+            try {
+              decode(rs, bl);
+            } catch (const JSONDecoder::err& e) {
+              cerr << "failed to decode JSON input: " << e.what() << std::endl;
+              return -EINVAL;
+            }
+            if (rs == rgw::sal::RGWRestoreStatus::RestoreAlreadyInProgress) {
+              restore_in_progress_count ++;
+            } else  if (rs == rgw::sal::RGWRestoreStatus::CloudRestored) {
+              restore_completed_count ++;
+            } else if (rs == rgw::sal::RGWRestoreStatus::RestoreFailed) {
+              restore_failed_count ++;
+            }
+          }
+        }
+      }
+    }
+  } while (results.is_truncated);
+  formatter->open_object_section("restore_stats");
+  formatter->dump_int("restore_completed_count", restore_completed_count);
+  formatter->dump_int("restore_in_progress_count", restore_in_progress_count);
+  formatter->dump_int("restore_failed_count", restore_failed_count);
+  formatter->close_section();
+  return 0;
+}
+
+static int bucket_stats(rgw::sal::Driver* driver,
+                        const std::string& tenant_name, const std::string& bucket_name,
+                        bool dump_restore_stats, Formatter* formatter,
+                        const DoutPrefixProvider* dpp, optional_yield y) {
+  std::unique_ptr<rgw::sal::Bucket> bucket;
   map<RGWObjCategory, RGWStorageStats> stats;
 
   int ret = driver->load_bucket(dpp, rgw_bucket(tenant_name, bucket_name),
@@ -1589,71 +1650,14 @@ static int bucket_stats(rgw::sal::Driver* driver,
   formatter->dump_int("read_tracker", bucket_info.objv_tracker.read_version.ver);
   // TODO: bucket CORS
   // TODO: bucket LC
-  formatter->close_section();
-
-  return 0;
-}
-
-static int bucket_restore_stats(rgw::sal::Driver* driver,
-                        const std::string& tenant_name,
-                        const std::string& bucket_name, Formatter* formatter,
-                        const DoutPrefixProvider* dpp, optional_yield y) {
-  std::unique_ptr<rgw::sal::Bucket> bucket;
-  int restore_completed_count = 0;
-  int restore_in_progress_count = 0;
-  int restore_failed_count = 0;
-  int ret = driver->load_bucket(dpp, rgw_bucket(tenant_name, bucket_name),
-                                &bucket, y);
-  if (ret < 0) {
-    return ret;
-  }
-  rgw::sal::Bucket::ListParams params;
-  rgw::sal::Bucket::ListResults results;
-  params.list_versions = bucket->versioned();
-  params.allow_unordered = true;
-  do {
-    ret = bucket->list(dpp, params, listing_max_entries, results, null_yield);
-    if (ret < 0) {
-      cerr << "ERROR: driver->list_objects(): " << cpp_strerror(-ret) << std::endl;
-      return ret;
-    }
-    for (vector<rgw_bucket_dir_entry>::iterator iter = results.objs.begin(); iter != results.objs.end(); ++iter) {
-      std::unique_ptr<rgw::sal::Object> obj = bucket->get_object(iter->key.name);
-      if (obj) {
-        ret = obj->get_obj_attrs(null_yield, dpp);
-        if (ret < 0) {
-          cerr << "ERROR: failed to stat object, returned error: " << cpp_strerror(-ret) << std::endl;
-          return ret;
-        }
-        for (map<string, bufferlist>::iterator getattriter = obj->get_attrs().begin(); getattriter != obj->get_attrs().end(); ++getattriter) {
-          bufferlist& bl = getattriter->second;
-          if (getattriter->first == RGW_ATTR_RESTORE_STATUS) {
-            rgw::sal::RGWRestoreStatus rs;
-            try {
-              decode(rs, bl);
-            } catch (const JSONDecoder::err& e) {
-              cerr << "failed to decode JSON input: " << e.what() << std::endl;
-              return -EINVAL;
-            }
-            if (rs == rgw::sal::RGWRestoreStatus::RestoreAlreadyInProgress) {
-              restore_in_progress_count ++;
-            } else  if (rs == rgw::sal::RGWRestoreStatus::CloudRestored) {
-              restore_completed_count ++;
-            } else if (rs == rgw::sal::RGWRestoreStatus::RestoreFailed) {
-              restore_failed_count ++;
-            }
-          }
-        }
+  if (dump_restore_stats) {
+      ret = bucket_restore_stats(driver, tenant_name, bucket_name, formatter, dpp, y);
+      if (ret < 0) {
+        return ret;
       }
-    }
-  } while (results.is_truncated);
-  formatter->open_object_section("");
-  formatter->open_object_section("restore_stats");
-  formatter->dump_int("restore_completed_count", restore_completed_count);
-  formatter->dump_int("restore_in_progress_count", restore_in_progress_count);
-  formatter->dump_int("restore_failed_count", restore_failed_count);
-  formatter->close_section();
+  }
   formatter->close_section();
+
   return 0;
 }
 
@@ -1793,7 +1797,7 @@ static int list_owner_bucket_info(const DoutPrefixProvider* dpp,
 
     for (const auto& ent : listing.buckets) {
       if (show_stats) {
-        bucket_stats(driver, tenant, ent.bucket.name, formatter, dpp, y);
+        bucket_stats(driver, tenant, ent.bucket.name, false, formatter, dpp, y);
       } else {
         formatter->dump_string("bucket", ent.bucket.name);
       }
@@ -1829,16 +1833,10 @@ int RGWBucketAdminOp::info(rgw::sal::Driver* driver,
   const bool show_stats = op_state.will_fetch_stats();
   const rgw_user& user_id = op_state.get_user_id();
   if (!bucket_name.empty()) {
-    ret = bucket_stats(driver, user_id.tenant, bucket_name, formatter, dpp, y);
+    ret = bucket_stats(driver, user_id.tenant, bucket_name, op_state.restore_stats, formatter, dpp, y);
     if (ret < 0) {
       return ret;
     }
-    if (op_state.restore_stats) {
-      ret = bucket_restore_stats(driver, user_id.tenant, bucket_name, formatter, dpp, y);
-      if (ret < 0) {
-        return ret;
-      }
-    }
   } else if (op_state.is_user_op()) {
     const rgw_user& uid = op_state.get_user_id();
     auto user = driver->get_user(uid);
@@ -1890,7 +1888,7 @@ int RGWBucketAdminOp::info(rgw::sal::Driver* driver,
                                                   &truncated);
       for (auto& bucket_name : buckets) {
         if (show_stats) {
-          bucket_stats(driver, user_id.tenant, bucket_name, formatter, dpp, y);
+          bucket_stats(driver, user_id.tenant, bucket_name, op_state.restore_stats, formatter, dpp, y);
        } else {
           formatter->dump_string("bucket", bucket_name);
        }
index 1d144b2885b97dd8d9676f31f4c4bc89b812ccee..e22523f5a6cafcf8f38a963038218bc8ff7caef4 100644 (file)
@@ -35,6 +35,7 @@ void RGWOp_Bucket_Info::execute(optional_yield y)
   RGWBucketAdminOpState op_state;
 
   bool fetch_stats;
+  bool fetch_restore_stats;
 
   std::string bucket;
 
@@ -45,10 +46,12 @@ void RGWOp_Bucket_Info::execute(optional_yield y)
 
   RESTArgs::get_string(s, "bucket", bucket, &bucket);
   RESTArgs::get_bool(s, "stats", false, &fetch_stats);
+  RESTArgs::get_bool(s, "restore-stats", false, &fetch_restore_stats);
 
   op_state.set_user_id(uid);
   op_state.set_bucket_name(bucket);
   op_state.set_fetch_stats(fetch_stats);
+  op_state.set_restore_stats(fetch_restore_stats);
 
   op_ret = RGWBucketAdminOp::info(driver, op_state, flusher, y, this);
 }
index 2f9951985b7ed3fe16396b4d7c12714095af4c54..d874e661561bbbfcfeecc10420bff3330a5d1632 100644 (file)
@@ -360,7 +360,7 @@ void usage()
   cout << "  notification rm                  remove a bucket notifications configuration\n";
   cout << "  restore status                   shows restoration status of object in a bucket\n";
   cout << "  restore list                     list restore status of each object in the bucket\n";
-  cout <<                                   can be filtered with help of --restore-status which shows objects with specified status\n";
+  cout << "                                   can be filtered with help of --restore-status which shows objects with specified status\n";
   cout << "options:\n";
   cout << "   --tenant=<tenant>                 tenant name\n";
   cout << "   --user_ns=<namespace>             namespace of user (oidc in case of users authenticated with oidc provider)\n";
index b360452838152edf5071e59d95c252e60fcca126..998b99860ffad9d9fad96db04c82f2671b28ef3e 100644 (file)
     notification list                list bucket notifications configuration
     notification get                 get a bucket notifications configuration
     notification rm                  remove a bucket notifications configuration
+    restore status                   shows restoration status of object in a bucket
+    restore list                     list restore status of each object in the bucket
+                                     can be filtered with help of --restore-status which shows objects with specified status
   options:
      --tenant=<tenant>                 tenant name
      --user_ns=<namespace>             namespace of user (oidc in case of users authenticated with oidc provider)
   Bucket list objects options:
      --max-entries                 max number of entries listed (default 1000)
      --marker                      the marker used to specify on which entry the listing begins, default none (i.e., very first entry)
+     --show-restore-stats          if the flag is in present it will show restores stats in the bucket stats command
   
     --conf/-c FILE    read configuration from the given configuration file
     --id ID           set ID portion of my name