From 949911d3d19d2e77835aaf34c5b8e597dadf4d02 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Wed, 3 Mar 2021 16:54:58 -0500 Subject: [PATCH] radosgw-admin: zone/zonegroup commands support --enable-feature=x --disable-feature=y Signed-off-by: Casey Bodley --- src/rgw/rgw_admin.cc | 86 +++++++++++++++++++++++++++++-- src/rgw/rgw_zone.cc | 25 +++++++++ src/rgw/rgw_zone.h | 2 + src/test/cli/radosgw-admin/help.t | 2 + 4 files changed, 112 insertions(+), 3 deletions(-) diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index bc38d592d78ed..e87bd678f1912 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -413,6 +413,8 @@ void usage() cout << " --trim-delay-ms time interval in msec to limit the frequency of sync error log entries trimming operations,\n"; cout << " the trimming process will sleep the specified msec for every 1000 entries trimmed\n"; cout << " --max-concurrent-ios maximum concurrent ios for bucket operations (default: 32)\n"; + cout << " --enable-feature enable a zone/zonegroup feature\n"; + cout << " --disable-feature disable a zone/zonegroup feature\n"; cout << "\n"; cout << " := \"YYYY-MM-DD[ hh:mm:ss]\"\n"; cout << "\nQuota options:\n"; @@ -3376,6 +3378,9 @@ int main(int argc, const char **argv) std::optional inject_error_at; std::optional inject_abort_at; + rgw::zone_features::set enable_features; + rgw::zone_features::set disable_features; + SimpleCmd cmd(all_cmds, cmd_aliases); bool raw_storage_op = false; @@ -3835,6 +3840,14 @@ int main(int argc, const char **argv) // do nothing } else if (ceph_argparse_witharg(args, i, &val, "--rgw-obj-fs", (char*)NULL)) { rgw_obj_fs = val; + } else if (ceph_argparse_witharg(args, i, &val, "--enable-feature", (char*)NULL)) { + if (!rgw::zone_features::supports(val)) { + std::cerr << "ERROR: Cannot enable unrecognized zone feature \"" << val << "\"" << std::endl; + return EINVAL; + } + enable_features.insert(val); + } else if (ceph_argparse_witharg(args, i, &val, "--disable-feature", (char*)NULL)) { + disable_features.insert(val); } else if (strncmp(*i, "-", 1) == 0) { cerr << "ERROR: invalid flag " << *i << std::endl; return EINVAL; @@ -4671,6 +4684,10 @@ int main(int argc, const char **argv) bool *psync_from_all = (sync_from_all_specified ? &sync_from_all : nullptr); string *predirect_zone = (redirect_zone_set ? &redirect_zone : nullptr); + if (enable_features.empty()) { // enable all features by default + enable_features.insert(rgw::zone_features::supported.begin(), + rgw::zone_features::supported.end()); + } ret = zonegroup.add_zone(dpp(), zone, (is_master_set ? &is_master : NULL), @@ -4679,7 +4696,7 @@ int main(int argc, const char **argv) psync_from_all, sync_from, sync_from_rm, predirect_zone, bucket_index_max_shards, static_cast(store)->svc()->sync_modules->get_manager(), - null_yield); + enable_features, disable_features, null_yield); if (ret < 0) { cerr << "failed to add zone " << zone_name << " to zonegroup " << zonegroup.get_name() << ": " << cpp_strerror(-ret) << std::endl; @@ -4705,6 +4722,22 @@ int main(int argc, const char **argv) RGWZoneGroup zonegroup(zonegroup_name, is_master, g_ceph_context, static_cast(store)->svc()->sysobj, realm.get_id(), endpoints); zonegroup.api_name = (api_name.empty() ? zonegroup_name : api_name); + + zonegroup.enabled_features = enable_features; + if (zonegroup.enabled_features.empty()) { // enable all features by default + zonegroup.enabled_features.insert(rgw::zone_features::supported.begin(), + rgw::zone_features::supported.end()); + } + for (const auto& feature : disable_features) { + auto i = zonegroup.enabled_features.find(feature); + if (i == zonegroup.enabled_features.end()) { + ldout(cct, 1) << "WARNING: zone feature \"" << feature + << "\" was not enabled in zonegroup " << zonegroup_name << dendl; + continue; + } + zonegroup.enabled_features.erase(i); + } + ret = zonegroup.create(dpp(), null_yield); if (ret < 0) { cerr << "failed to create zonegroup " << zonegroup_name << ": " << cpp_strerror(-ret) << std::endl; @@ -4856,6 +4889,22 @@ int main(int argc, const char **argv) need_update = true; } + for (const auto& feature : enable_features) { + zonegroup.enabled_features.insert(feature); + need_update = true; + } + for (const auto& feature : disable_features) { + auto i = zonegroup.enabled_features.find(feature); + if (i == zonegroup.enabled_features.end()) { + ldout(cct, 1) << "WARNING: zone feature \"" << feature + << "\" was not enabled in zonegroup " + << zonegroup.get_name() << dendl; + continue; + } + zonegroup.enabled_features.erase(i); + need_update = true; + } + if (need_update) { ret = zonegroup.update(dpp(), null_yield); if (ret < 0) { @@ -4900,6 +4949,32 @@ int main(int argc, const char **argv) if (zonegroup.realm_id.empty() && !default_realm_not_exist) { zonegroup.realm_id = realm.get_id(); } + // validate zonegroup features + for (const auto& feature : zonegroup.enabled_features) { + if (!rgw::zone_features::supports(feature)) { + std::cerr << "ERROR: Unrecognized zonegroup feature \"" + << feature << "\"" << std::endl; + return EINVAL; + } + } + for (const auto& [name, zone] : zonegroup.zones) { + // validate zone features + for (const auto& feature : zone.supported_features) { + if (!rgw::zone_features::supports(feature)) { + std::cerr << "ERROR: Unrecognized zone feature \"" + << feature << "\" in zone " << zone.name << std::endl; + return EINVAL; + } + } + // zone must support everything zonegroup does + for (const auto& feature : zonegroup.enabled_features) { + if (!zone.supports(feature)) { + std::cerr << "ERROR: Zone " << name << " does not support feature \"" + << feature << "\" required by zonegroup" << std::endl; + return EINVAL; + } + } + } ret = zonegroup.create(dpp(), null_yield); if (ret < 0 && ret != -EEXIST) { cerr << "ERROR: couldn't create zonegroup info: " << cpp_strerror(-ret) << std::endl; @@ -5145,6 +5220,11 @@ int main(int argc, const char **argv) string *ptier_type = (tier_type_specified ? &tier_type : nullptr); bool *psync_from_all = (sync_from_all_specified ? &sync_from_all : nullptr); string *predirect_zone = (redirect_zone_set ? &redirect_zone : nullptr); + if (enable_features.empty()) { // enable all features by default + enable_features.insert(rgw::zone_features::supported.begin(), + rgw::zone_features::supported.end()); + } + ret = zonegroup.add_zone(dpp(), zone, (is_master_set ? &is_master : NULL), (is_read_only_set ? &read_only : NULL), @@ -5154,7 +5234,7 @@ int main(int argc, const char **argv) sync_from, sync_from_rm, predirect_zone, bucket_index_max_shards, static_cast(store)->svc()->sync_modules->get_manager(), - null_yield); + enable_features, disable_features, null_yield); if (ret < 0) { cerr << "failed to add zone " << zone_name << " to zonegroup " << zonegroup.get_name() << ": " << cpp_strerror(-ret) << std::endl; @@ -5434,7 +5514,7 @@ int main(int argc, const char **argv) psync_from_all, sync_from, sync_from_rm, predirect_zone, bucket_index_max_shards, static_cast(store)->svc()->sync_modules->get_manager(), - null_yield); + enable_features, disable_features, null_yield); if (ret < 0) { cerr << "failed to update zonegroup: " << cpp_strerror(-ret) << std::endl; return -ret; diff --git a/src/rgw/rgw_zone.cc b/src/rgw/rgw_zone.cc index 9dd98d43f5dff..649c8993e7398 100644 --- a/src/rgw/rgw_zone.cc +++ b/src/rgw/rgw_zone.cc @@ -109,6 +109,11 @@ int RGWZoneGroup::create_default(const DoutPrefixProvider *dpp, optional_yield y default_zone.name = zone_params.get_name(); default_zone.id = zone_params.get_id(); master_zone = default_zone.id; + + // enable all supported features + enabled_features.insert(rgw::zone_features::supported.begin(), + rgw::zone_features::supported.end()); + default_zone.supported_features = enabled_features; r = create(dpp, y); if (r < 0 && r != -EEXIST) { @@ -189,6 +194,8 @@ int RGWZoneGroup::add_zone(const DoutPrefixProvider *dpp, bool *psync_from_all, list& sync_from, list& sync_from_rm, string *predirect_zone, std::optional bucket_index_max_shards, RGWSyncModulesManager *sync_mgr, + const rgw::zone_features::set& enable_features, + const rgw::zone_features::set& disable_features, optional_yield y) { auto& zone_id = zone_params.get_id(); @@ -256,6 +263,24 @@ int RGWZoneGroup::add_zone(const DoutPrefixProvider *dpp, zone.sync_from.erase(rm); } + zone.supported_features.insert(enable_features.begin(), + enable_features.end()); + + for (const auto& feature : disable_features) { + if (enabled_features.contains(feature)) { + lderr(cct) << "ERROR: Cannot disable zone feature \"" << feature + << "\" until it's been disabled in zonegroup " << name << dendl; + return -EINVAL; + } + auto i = zone.supported_features.find(feature); + if (i == zone.supported_features.end()) { + ldout(cct, 1) << "WARNING: zone feature \"" << feature + << "\" was not enabled in zone " << zone.name << dendl; + continue; + } + zone.supported_features.erase(i); + } + post_process_params(dpp, y); return update(dpp,y); diff --git a/src/rgw/rgw_zone.h b/src/rgw/rgw_zone.h index e2b2d30da1bb1..640a48ce61f1f 100644 --- a/src/rgw/rgw_zone.h +++ b/src/rgw/rgw_zone.h @@ -842,6 +842,8 @@ struct RGWZoneGroup : public RGWSystemMetaObj { bool *psync_from_all, std::list& sync_from, std::list& sync_from_rm, std::string *predirect_zone, std::optional bucket_index_max_shards, RGWSyncModulesManager *sync_mgr, + const rgw::zone_features::set& enable_features, + const rgw::zone_features::set& disable_features, optional_yield y); int remove_zone(const DoutPrefixProvider *dpp, const std::string& zone_id, optional_yield y); int rename_zone(const DoutPrefixProvider *dpp, const RGWZoneParams& zone_params, optional_yield y); diff --git a/src/test/cli/radosgw-admin/help.t b/src/test/cli/radosgw-admin/help.t index 4971c4d2510ff..1c3184466f245 100644 --- a/src/test/cli/radosgw-admin/help.t +++ b/src/test/cli/radosgw-admin/help.t @@ -304,6 +304,8 @@ --trim-delay-ms time interval in msec to limit the frequency of sync error log entries trimming operations, the trimming process will sleep the specified msec for every 1000 entries trimmed --max-concurrent-ios maximum concurrent ios for bucket operations (default: 32) + --enable-feature enable a zone/zonegroup feature + --disable-feature disable a zone/zonegroup feature := "YYYY-MM-DD[ hh:mm:ss]" -- 2.39.5