]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
radosgw-admin: zone/zonegroup commands support --enable-feature=x --disable-feature=y
authorCasey Bodley <cbodley@redhat.com>
Wed, 3 Mar 2021 21:54:58 +0000 (16:54 -0500)
committerAdam C. Emerson <aemerson@redhat.com>
Tue, 1 Feb 2022 21:22:23 +0000 (16:22 -0500)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/rgw_admin.cc
src/rgw/rgw_zone.cc
src/rgw/rgw_zone.h
src/test/cli/radosgw-admin/help.t

index d80376f93b3f3118fbaa61f9fab3de702b3c4dd8..bc0699aeed1edac449c6f303b8dd154cf465308a 100644 (file)
@@ -423,6 +423,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 << "<date> := \"YYYY-MM-DD[ hh:mm:ss]\"\n";
   cout << "\nQuota options:\n";
@@ -3598,6 +3600,9 @@ int main(int argc, const char **argv)
   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;
 
@@ -4087,6 +4092,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;
@@ -5020,6 +5033,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),
@@ -5028,7 +5045,7 @@ int main(int argc, const char **argv)
                                  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;
@@ -5054,6 +5071,22 @@ int main(int argc, const char **argv)
 
        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;
@@ -5205,6 +5238,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) {
@@ -5249,6 +5298,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;
@@ -5556,6 +5631,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),
@@ -5565,7 +5645,7 @@ int main(int argc, const char **argv)
                                    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;
@@ -5845,7 +5925,7 @@ int main(int argc, const char **argv)
                                  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;
index 5daffe58a8ac99335b2634af56bd4a1586134000..807cc3046ec06f0d1672278fc1ed7bf43f05cd59 100644 (file)
@@ -122,6 +122,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) {
@@ -202,6 +207,8 @@ int RGWZoneGroup::add_zone(const DoutPrefixProvider *dpp,
                            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();
@@ -269,6 +276,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);
index ba11464ab0c9fc5e7ef032870aa7e4232f133f42..287b60e67351fde4a3a64b4d8f7528c0fac8e36e 100644 (file)
@@ -990,6 +990,8 @@ struct RGWZoneGroup : public RGWSystemMetaObj {
                bool *psync_from_all, std::list<std::string>& sync_from,
                std::list<std::string>& sync_from_rm, std::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);
   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);
index 6c30ef3df8b3389087f9223b2de82c4eb013a004..bad7221241f6c4d53c79a18a924e0b3aaa435d2b 100644 (file)
      --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
   
   <date> := "YYYY-MM-DD[ hh:mm:ss]"