From: Casey Bodley Date: Tue, 4 Feb 2025 16:09:12 +0000 (-0500) Subject: radosgw-admin: support 'account rm --purge-data' X-Git-Tag: v20.3.0~460^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=83bacbb47457dea380ac1958f73c82132a8f7fd4;p=ceph.git radosgw-admin: support 'account rm --purge-data' analogous to 'user rm --purge-data'. instead of failing if the account still owns buckets, remove the remaining buckets/objects Signed-off-by: Casey Bodley --- diff --git a/src/rgw/radosgw-admin/radosgw-admin.cc b/src/rgw/radosgw-admin/radosgw-admin.cc index 991f9779f0d06..21dd8f2af1688 100644 --- a/src/rgw/radosgw-admin/radosgw-admin.cc +++ b/src/rgw/radosgw-admin/radosgw-admin.cc @@ -11904,6 +11904,7 @@ next: .max_groups = max_groups, .max_access_keys = max_access_keys, .max_buckets = max_buckets, + .purge_data = static_cast(purge_data), }; std::string err_msg; diff --git a/src/rgw/rgw_account.cc b/src/rgw/rgw_account.cc index af61be8b500e0..fd9c479337ce0 100644 --- a/src/rgw/rgw_account.cc +++ b/src/rgw/rgw_account.cc @@ -312,15 +312,36 @@ int remove(const DoutPrefixProvider* dpp, constexpr bool need_stats = false; rgw::sal::BucketList buckets; - ret = driver->list_buckets(dpp, info.id, info.tenant, marker, marker, - max_items, need_stats, buckets, y); - if (ret < 0) { - return ret; - } - if (!buckets.buckets.empty()) { - err_msg = "The account cannot be deleted until all buckets are removed."; - return -ENOTEMPTY; - } + do { + ret = driver->list_buckets(dpp, info.id, info.tenant, + buckets.next_marker, "", + max_items, need_stats, buckets, y); + if (ret < 0) { + err_msg = "Unable to list account buckets"; + return ret; + } + + if (!buckets.buckets.empty() && !op_state.purge_data) { + err_msg = "The account cannot be deleted until all buckets are removed."; + return -EEXIST; // change to code that maps to 409: conflict + } + + for (const auto& ent : buckets.buckets) { + std::unique_ptr bucket; + ret = driver->load_bucket(dpp, ent.bucket, &bucket, y); + if (ret < 0) { + err_msg = fmt::format("unable to load bucket {}", ent.bucket.name); + return ret; + } + + constexpr bool delete_objects = true; + ret = bucket->remove(dpp, delete_objects, y); + if (ret < 0) { + err_msg = fmt::format("unable to delete bucket {}", ent.bucket.name); + return ret; + } + } + } while (!buckets.next_marker.empty()); rgw::sal::RoleList roles; ret = driver->list_account_roles(dpp, y, info.id, path_prefix, diff --git a/src/rgw/rgw_account.h b/src/rgw/rgw_account.h index 2a6f3e2379751..d3c9055f10143 100644 --- a/src/rgw/rgw_account.h +++ b/src/rgw/rgw_account.h @@ -53,6 +53,7 @@ struct AdminOpState { std::optional quota_max_size; std::optional quota_max_objects; std::optional quota_enabled; + bool purge_data = false; }; /// create an account