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 << "<date> := \"YYYY-MM-DD[ hh:mm:ss]\"\n";
cout << "\nQuota options:\n";
std::optional<std::string> inject_error_at;
std::optional<std::string> 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;
// 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;
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),
psync_from_all, sync_from, sync_from_rm,
predirect_zone, bucket_index_max_shards,
static_cast<rgw::sal::RadosStore*>(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;
RGWZoneGroup zonegroup(zonegroup_name, is_master, g_ceph_context, static_cast<rgw::sal::RadosStore*>(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;
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) {
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;
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),
sync_from, sync_from_rm,
predirect_zone, bucket_index_max_shards,
static_cast<rgw::sal::RadosStore*>(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;
psync_from_all, sync_from, sync_from_rm,
predirect_zone, bucket_index_max_shards,
static_cast<rgw::sal::RadosStore*>(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;
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) {
bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm,
string *predirect_zone, std::optional<int> 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();
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);