]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/CloudTransition: Add new options to configure tier endpoint
authorSoumya Koduri <skoduri@redhat.com>
Sat, 11 Jul 2020 17:05:04 +0000 (22:35 +0530)
committerSoumya Koduri <skoduri@redhat.com>
Thu, 18 Nov 2021 07:22:47 +0000 (12:52 +0530)
As mentioned in https://docs.google.com/document/d/1IoeITPCF64A5W-UA-9Y3Vp2oSfz3xVQHu31GTu3u3Ug/edit,
the tier storage class will be configured at zonegroup level.

So the existing CLI "radosgw-admin zonegroup placement add  <id> --storage-class <class>" will be
used to add tier storage classes as well but with extra tier-config options mentioned below -

--tier-type : "cloud"
--tier-config : [<key,value>,]

These tier options are already defined to configure cloud sync module which are being reused here.

TODO:
* Add multipart options (if any , like part size, threshold)
* Document
* Test upgrade/downgrade

Signed-off-by: Soumya Koduri <skoduri@redhat.com>
src/rgw/rgw_admin.cc
src/rgw/rgw_json_enc.cc
src/rgw/rgw_zone.cc
src/rgw/rgw_zone.h

index 703930045722f490de2af9782e26c048bfcac9eb..2378499fa94ef49b93af5f75a58251c9bcd8f0be 100644 (file)
@@ -5049,6 +5049,57 @@ int main(int argc, const char **argv)
             target.tags.insert(t);
           }
           target.storage_classes.insert(rule.get_storage_class());
+
+          /* Tier options */
+          bool tier_class = false;
+          std::string storage_class = rule.get_storage_class();
+          RGWZoneGroupPlacementTier t{storage_class};
+          RGWZoneGroupPlacementTier *pt = &t;
+
+         auto ptiter = target.tier_targets.find(storage_class);
+         if (ptiter != target.tier_targets.end()) {
+            pt = &ptiter->second;
+            tier_class = true;
+          } else if (tier_type_specified && tier_type == "cloud") {
+            /* we support only cloud tier-type for now.
+             * Once set cant be reset. */
+            tier_class = true;
+            pt->tier_type = tier_type;
+          }
+
+          if (tier_class) {
+            if (tier_config_add.size() > 0) {
+              JSONFormattable tconfig;
+              for (auto add : tier_config_add) {
+                int r = tconfig.set(add.first, add.second);
+                if (r < 0) {
+                  cerr << "ERROR: failed to set configurable: " << add << std::endl;
+                  return EINVAL;
+                }
+              }
+              int r = pt->update_params(tconfig);
+              if (r < 0) {
+                cerr << "ERROR: failed to update tier_config options"<< std::endl;
+              }
+            }
+            if (tier_config_rm.size() > 0) {
+              JSONFormattable tconfig;
+              for (auto add : tier_config_rm) {
+                int r = tconfig.set(add.first, add.second);
+                if (r < 0) {
+                  cerr << "ERROR: failed to set configurable: " << add << std::endl;
+                  return EINVAL;
+                }
+              }
+              int r = pt->clear_params(tconfig);
+              if (r < 0) {
+                cerr << "ERROR: failed to update tier_config options"<< std::endl;
+              }
+            }
+
+            target.tier_targets.emplace(std::make_pair(storage_class, *pt));
+          }
+
         } else if (opt_cmd == OPT::ZONEGROUP_PLACEMENT_RM) {
           if (!opt_storage_class ||
               opt_storage_class->empty()) {
index 99892a44baee4452802a33ae2f6ee8466a1d9fd3..9f8ab1626c26cfbe727f592b71f9844ddde02614 100644 (file)
@@ -1402,11 +1402,80 @@ void RGWZone::decode_json(JSONObj *obj)
   JSONDecoder::decode_json("redirect_zone", redirect_zone, obj);
 }
 
+void RGWTierACLMapping::dump(Formatter *f) const
+{
+  string s;
+  switch (type) {
+    case ACL_TYPE_EMAIL_USER:
+      s = "email";
+      break;
+    case ACL_TYPE_GROUP:
+      s = "uri";
+      break;
+    default:
+      s = "id";
+      break;
+  }
+  encode_json("type", s, f);
+  encode_json("source_id", source_id, f);
+  encode_json("dest_id", dest_id, f);
+}
+
+void RGWTierACLMapping::decode_json(JSONObj *obj)
+{
+  string s;
+  JSONDecoder::decode_json("type", s, obj);
+  if (s == "email") {
+    type = ACL_TYPE_EMAIL_USER;
+  } else if (s == "uri") {
+    type = ACL_TYPE_GROUP;
+  } else {
+    type = ACL_TYPE_CANON_USER;
+  }
+
+  JSONDecoder::decode_json("source_id", source_id, obj);
+  JSONDecoder::decode_json("dest_id", dest_id, obj);
+}
+
+void RGWZoneGroupPlacementTier::dump(Formatter *f) const
+{
+  encode_json("storage_class", storage_class, f);
+  encode_json("tier_type", tier_type, f);
+  encode_json("endpoint", endpoint, f);
+  encode_json("access_key", key.id, f);
+  encode_json("secret", key.key, f);
+  string s = (host_style == PathStyle ? "path" : "virtual");
+  encode_json("host_style", s, f);
+  encode_json("tier_storage_class", tier_storage_class, f);
+  encode_json("target_path", target_path, f);
+  encode_json("acl_mappings", acl_mappings, f);
+}
+
+void RGWZoneGroupPlacementTier::decode_json(JSONObj *obj)
+{
+  JSONDecoder::decode_json("storage_class", storage_class, obj);
+  JSONDecoder::decode_json("tier_type", tier_type, obj);
+  JSONDecoder::decode_json("endpoint", endpoint, obj);
+  JSONDecoder::decode_json("access_key", key.id, obj);
+  JSONDecoder::decode_json("secret", key.key, obj);
+  string s;
+  JSONDecoder::decode_json("host_style", s, obj);
+  if (s != "virtual") {
+    host_style = PathStyle;
+  } else {
+    host_style = VirtualStyle;
+  }
+  JSONDecoder::decode_json("tier_storage_class", tier_storage_class, obj);
+  JSONDecoder::decode_json("target_path", target_path, obj);
+  JSONDecoder::decode_json("acl_mappings", acl_mappings, obj);
+}
+
 void RGWZoneGroupPlacementTarget::dump(Formatter *f) const
 {
   encode_json("name", name, f);
   encode_json("tags", tags, f);
   encode_json("storage_classes", storage_classes, f);
+  encode_json("tier_targets", tier_targets, f);
 }
 
 void RGWZoneGroupPlacementTarget::decode_json(JSONObj *obj)
@@ -1417,6 +1486,7 @@ void RGWZoneGroupPlacementTarget::decode_json(JSONObj *obj)
   if (storage_classes.empty()) {
     storage_classes.insert(RGW_STORAGE_CLASS_STANDARD);
   }
+  JSONDecoder::decode_json("tier_targets", tier_targets, obj);
 }
 
 void RGWZoneGroup::dump(Formatter *f) const
index 6d9f8b05140ad3159fdf9cf64a36501a7176b1bc..1d013ae5a97c01db48aec1b1617320e25d19637f 100644 (file)
@@ -2081,4 +2081,88 @@ void RGWZoneGroupMap::decode(bufferlist::const_iterator& bl) {
   }
 }
 
+int RGWZoneGroupPlacementTier::update_params(const JSONFormattable& config)
+{
+
+  if (config.exists("endpoint")) {
+    endpoint = config["endpoint"];
+  }
+  if (config.exists("target_path")) {
+    target_path = config["target_path"];
+  }
+  if (config.exists("host_style")) {
+    string s;
+    s = config["host_style"];
+    if (s != "virtual") {
+      host_style = PathStyle;
+    } else {
+      host_style = VirtualStyle;
+    }
+  }
+  if (config.exists("tier_storage_class")) {
+    tier_storage_class = config["tier_storage_class"];
+  }
+  if (config.exists("access_key")) {
+    key.id = config["access_key"];
+  }
+  if (config.exists("secret")) {
+    key.key = config["secret"];
+  }
+  if (config.exists("acls")) {
+    const JSONFormattable& cc = config["acls"];
+    if (cc.is_array()) {
+      for (auto& c : cc.array()) {
+        RGWTierACLMapping m;
+        m.init(c);
+        if (!m.source_id.empty()) {
+          acl_mappings[m.source_id] = m;
+        }
+      }
+    } else {
+      RGWTierACLMapping m;
+      m.init(cc);
+      if (!m.source_id.empty()) {
+        acl_mappings[m.source_id] = m;
+      }
+    }
+  }
+  return 0;
+}
+int RGWZoneGroupPlacementTier::clear_params(const JSONFormattable& config)
+{
+  if (config.exists("endpoint")) {
+    endpoint.clear();
+  }
+  if (config.exists("target_path")) {
+    target_path.clear();
+  }
+  if (config.exists("host_style")) {
+    /* default */
+    host_style = PathStyle;
+  }
+  if (config.exists("tier_storage_class")) {
+    tier_storage_class.clear();
+  }
+  if (config.exists("access_key")) {
+    key.id.clear();
+  }
+  if (config.exists("secret")) {
+    key.key.clear();
+  }
+  if (config.exists("acls")) {
+    const JSONFormattable& cc = config["acls"];
+    if (cc.is_array()) {
+      for (auto& c : cc.array()) {
+        RGWTierACLMapping m;
+        m.init(c);
+        acl_mappings.erase(m.source_id);
+      }
+    } else {
+      RGWTierACLMapping m;
+      m.init(cc);
+      acl_mappings.erase(m.source_id);
+    }
+  }
+  return 0;
+}
 
index 2823d54fc71bb8b6ed83cab8e3069f898928c455..c145ca1b8423b0a38de3d71fc6dcd21feccded7f 100644 (file)
@@ -679,10 +679,131 @@ struct RGWDefaultZoneGroupInfo {
 };
 WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo)
 
+struct RGWTierACLMapping {
+  ACLGranteeTypeEnum type{ACL_TYPE_CANON_USER};
+  std::string source_id;
+  std::string dest_id;
+
+  RGWTierACLMapping() = default;
+
+  RGWTierACLMapping(ACLGranteeTypeEnum t,
+             const string& s,
+             const string& d) : type(t),
+  source_id(s),
+  dest_id(d) {}
+
+  void init(const JSONFormattable& config) {
+    const string& t = config["type"];
+
+    if (t == "email") {
+      type = ACL_TYPE_EMAIL_USER;
+    } else if (t == "uri") {
+      type = ACL_TYPE_GROUP;
+    } else {
+      type = ACL_TYPE_CANON_USER;
+    }
+
+    source_id = config["source_id"];
+    dest_id = config["dest_id"];
+  }
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    string s;
+    switch (type) {
+      case ACL_TYPE_EMAIL_USER:
+        s = "email";
+        break;
+      case ACL_TYPE_GROUP:
+        s = "uri";
+        break;
+      default:
+        s = "id";
+        break;
+    }
+    encode(s, bl);
+    encode(source_id, bl);
+    encode(dest_id, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+      string s;
+     decode(s, bl);
+     if (s == "email") {
+        type = ACL_TYPE_EMAIL_USER;
+     } else if (s == "uri") {
+        type = ACL_TYPE_GROUP;
+     } else {
+        type = ACL_TYPE_CANON_USER;
+     }
+    decode(source_id, bl);
+    decode(dest_id, bl);
+    DECODE_FINISH(bl);
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWTierACLMapping)
+
+struct RGWZoneGroupPlacementTier {
+  std::string storage_class;
+  std::string tier_type;
+  std::string endpoint;
+  RGWAccessKey key;
+  HostStyle host_style{PathStyle};
+  string tier_storage_class;
+
+  /* Should below be bucket/zone specific?? */
+  string target_path;
+  map<string, RGWTierACLMapping> acl_mappings;
+
+  int update_params(const JSONFormattable& config);
+  int clear_params(const JSONFormattable& config);
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(storage_class, bl);
+    encode(tier_type, bl);
+    encode(endpoint, bl);
+    encode(key, bl);
+    string s = (host_style == PathStyle ? "path" : "virtual");
+    encode(s, bl);
+    encode(tier_storage_class, bl);
+    encode(target_path, bl);
+    encode(acl_mappings, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+    decode(storage_class, bl);
+    decode(tier_type, bl);
+    decode(endpoint, bl);
+    decode(key, bl);
+    string s;
+    decode(s, bl);
+    if (s != "virtual") {
+      host_style = PathStyle;
+    } else {
+      host_style = VirtualStyle;
+    }
+    decode(tier_storage_class, bl);
+    decode(target_path, bl);
+    decode(acl_mappings, bl);
+    DECODE_FINISH(bl);
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTier)
+
 struct RGWZoneGroupPlacementTarget {
   std::string name;
   std::set<std::string> tags;
   std::set<std::string> storage_classes;
+  std::map<std::string, RGWZoneGroupPlacementTier> tier_targets;
 
   bool user_permitted(const std::list<std::string>& user_tags) const {
     if (tags.empty()) {
@@ -697,15 +818,16 @@ struct RGWZoneGroupPlacementTarget {
   }
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(2, 1, bl);
+    ENCODE_START(3, 1, bl);
     encode(name, bl);
     encode(tags, bl);
     encode(storage_classes, bl);
+    encode(tier_targets, bl);
     ENCODE_FINISH(bl);
   }
 
   void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(2, bl);
+    DECODE_START(3, bl);
     decode(name, bl);
     decode(tags, bl);
     if (struct_v >= 2) {
@@ -714,6 +836,9 @@ struct RGWZoneGroupPlacementTarget {
     if (storage_classes.empty()) {
       storage_classes.insert(RGW_STORAGE_CLASS_STANDARD);
     }
+    if (struct_v >= 3) {
+      decode(tier_targets, bl);
+    }
     DECODE_FINISH(bl);
   }
   void dump(Formatter *f) const;