]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add support for storage class
authorYehuda Sadeh <yehuda@redhat.com>
Fri, 15 Jun 2018 01:17:01 +0000 (18:17 -0700)
committerYehuda Sadeh <yehuda@redhat.com>
Fri, 4 Jan 2019 02:01:37 +0000 (18:01 -0800)
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
16 files changed:
src/rgw/rgw_admin.cc
src/rgw/rgw_bucket.cc
src/rgw/rgw_common.h
src/rgw/rgw_json_enc.cc
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_putobj_processor.h
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_zone.cc
src/rgw/rgw_zone.h
src/rgw/services/svc_zone.cc
src/rgw/services/svc_zone.h

index f28ccf9972853b0aeeafde1fd89ea5a638b29928..d056c0287015ae29c37d5d34909139d8e4baf734 100644 (file)
@@ -289,6 +289,7 @@ void usage()
   cout << "   --read-only               set zone as read-only (when adding to zonegroup)\n";
   cout << "   --redirect-zone           specify zone id to redirect when response is 404 (not found)\n";
   cout << "   --placement-id            placement id for zonegroup placement commands\n";
+  cout << "   --storage-class           storage class for zonegroup placement commands\n";
   cout << "   --tags=<list>             list of tags for zonegroup placement add and modify commands\n";
   cout << "   --tags-add=<list>         list of tags to add for zonegroup placement modify command\n";
   cout << "   --tags-rm=<list>          list of tags to remove for zonegroup placement modify command\n";
@@ -2800,6 +2801,7 @@ int main(int argc, const char **argv)
   string quota_scope;
   string object_version;
   string placement_id;
+  string storage_class;
   list<string> tags;
   list<string> tags_add;
   list<string> tags_rm;
@@ -3112,6 +3114,8 @@ int main(int argc, const char **argv)
       zonegroup_new_name = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--placement-id", (char*)NULL)) {
       placement_id = val;
+    } else if (ceph_argparse_witharg(args, i, &val, "--storage-class", (char*)NULL)) {
+      storage_class = val;
     } else if (ceph_argparse_witharg(args, i, &val, "--tags", (char*)NULL)) {
       get_str_list(val, tags);
     } else if (ceph_argparse_witharg(args, i, &val, "--tags-add", (char*)NULL)) {
@@ -4289,6 +4293,17 @@ int main(int argc, const char **argv)
           return EINVAL;
         }
 
+        rgw_placement_rule rule;
+        rule.from_str(placement_id);
+
+        if (!rule.storage_class.empty() && !storage_class.empty() &&
+            rule.storage_class != storage_class) {
+          cerr << "ERROR: provided contradicting storage class configuration" << std::endl;
+          return EINVAL;
+        } else if (rule.storage_class.empty()) {
+          rule.storage_class = storage_class;
+        }
+
        RGWZoneGroup zonegroup(zonegroup_id, zonegroup_name);
        int ret = zonegroup.init(g_ceph_context, store->svc.sysobj);
        if (ret < 0) {
@@ -4296,14 +4311,8 @@ int main(int argc, const char **argv)
          return -ret;
        }
 
-        if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_ADD) {
-          RGWZoneGroupPlacementTarget target;
-          target.name = placement_id;
-          for (auto& t : tags) {
-            target.tags.insert(t);
-          }
-          zonegroup.placement_targets[placement_id] = target;
-        } else if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_MODIFY) {
+        if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_ADD ||
+            opt_cmd == OPT_ZONEGROUP_PLACEMENT_MODIFY) {
           RGWZoneGroupPlacementTarget& target = zonegroup.placement_targets[placement_id];
           if (!tags.empty()) {
             target.tags.clear();
@@ -4318,6 +4327,7 @@ int main(int argc, const char **argv)
           for (auto& t : tags_add) {
             target.tags.insert(t);
           }
+          target.storage_classes.insert(rule.get_storage_class());
         } else if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_RM) {
           zonegroup.placement_targets.erase(placement_id);
         } else if (opt_cmd == OPT_ZONEGROUP_PLACEMENT_DEFAULT) {
@@ -4326,7 +4336,7 @@ int main(int argc, const char **argv)
                 << placement_id << "'" << std::endl;
             return -ENOENT;
           }
-          zonegroup.default_placement = placement_id;
+          zonegroup.default_placement = rule;
         }
 
         zonegroup.post_process_params();
@@ -4770,7 +4780,11 @@ int main(int argc, const char **argv)
           RGWZonePlacementInfo& info = zone.placement_pools[placement_id];
 
           info.index_pool = *index_pool;
-          info.data_pool = *data_pool;
+          if (storage_class.empty()) {
+            info.data_pools[RGW_STORAGE_CLASS_STANDARD] = *data_pool;
+          } else {
+            info.data_pools[storage_class] = *data_pool;
+          }
           if (data_extra_pool) {
             info.data_extra_pool = *data_extra_pool;
           }
@@ -4799,7 +4813,11 @@ int main(int argc, const char **argv)
             info.index_pool = *index_pool;
           }
           if (data_pool && !data_pool->empty()) {
-            info.data_pool = *data_pool;
+            if (storage_class.empty()) {
+              info.data_pools[RGW_STORAGE_CLASS_STANDARD] = *data_pool;
+            } else {
+              info.data_pools[storage_class] = *data_pool;
+            }
           }
           if (data_extra_pool) {
             info.data_extra_pool = *data_extra_pool;
index 19c534f381f2cf2cef8c7e285876ab59b99017f3..3ff965ec510d8638d16041a5f85fa44a8ec56c5c 100644 (file)
@@ -1436,7 +1436,7 @@ static int bucket_stats(RGWRados *store, const std::string& tenant_name, std::st
   formatter->dump_string("bucket", bucket.name);
   formatter->dump_string("tenant", bucket.tenant);
   formatter->dump_string("zonegroup", bucket_info.zonegroup);
-  formatter->dump_string("placement_rule", bucket_info.placement_rule);
+  formatter->dump_string("placement_rule", bucket_info.placement_rule.to_str());
   ::encode_json("explicit_placement", bucket.explicit_placement, formatter);
   formatter->dump_string("id", bucket.bucket_id);
   formatter->dump_string("marker", bucket.marker);
index 146074540877516dde5c326f02dc6826ff61a776..26ee460390dc324689726e268a60502b98c44dc4 100644 (file)
@@ -78,6 +78,7 @@ using ceph::crypto::MD5;
  * user through custom HTTP header named X-Static-Large-Object. */
 #define RGW_ATTR_SLO_UINDICATOR RGW_ATTR_META_PREFIX "static-large-object"
 #define RGW_ATTR_X_ROBOTS_TAG  RGW_ATTR_PREFIX "x-robots-tag"
+#define RGW_ATTR_STORAGE_CLASS  RGW_ATTR_PREFIX "storage_class"
 
 #define RGW_ATTR_PG_VER        RGW_ATTR_PREFIX "pg_ver"
 #define RGW_ATTR_SOURCE_ZONE    RGW_ATTR_PREFIX "source_zone"
@@ -649,6 +650,97 @@ enum RGWIdentityType
   TYPE_ROLE=4
 };
 
+static string RGW_STORAGE_CLASS_STANDARD = "STANDARD";
+
+struct rgw_placement_rule {
+  std::string name;
+  std::string storage_class;
+
+  rgw_placement_rule() {}
+  rgw_placement_rule(const string& _n, const string& _sc) : name(_n), storage_class(_sc) {}
+
+
+  bool empty() const {
+    return name.empty() && storage_class.empty();
+  }
+
+  void clear() {
+    name.clear();
+    storage_class.clear();
+  }
+
+  void init(const string& n, const string& c) {
+    name = n;
+    storage_class = c;
+  }
+
+  const string& get_storage_class() const {
+    if (storage_class.empty()) {
+      return RGW_STORAGE_CLASS_STANDARD;
+    }
+    return storage_class;
+  }
+  
+  int compare(const rgw_placement_rule& r) const {
+    int c = name.compare(r.name);
+    if (c != 0) {
+      return c;
+    }
+    return get_storage_class().compare(r.get_storage_class());
+  }
+
+  bool operator==(const rgw_placement_rule& r) const {
+    return (name == r.name &&
+            get_storage_class() == r.get_storage_class());
+  }
+
+  bool operator!=(const rgw_placement_rule& r) const {
+    return !(*this == r);
+  }
+
+  void encode(bufferlist& bl) const {
+    /* no ENCODE_START/END due to backward compatibility */
+    std::string s = to_str();
+    ceph::encode(s, bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    std::string s;
+    ceph::decode(s, bl);
+    from_str(s);
+  } 
+
+  std::string to_str() const {
+    if (standard_storage_class()) {
+      return name;
+    }
+    return name + "/" + storage_class;
+  }
+
+  void from_str(const std::string& s) {
+    size_t pos = s.find("/");
+    if (pos == std::string::npos) {
+      name = s;
+      return;
+    }
+    name = s.substr(0, pos);
+    if (pos < s.size() - 1) {
+      storage_class = s.substr(pos + 1);
+    }
+  }
+
+  bool standard_storage_class() const {
+    return storage_class.empty() || storage_class == RGW_STORAGE_CLASS_STANDARD;
+  }
+};
+WRITE_CLASS_ENCODER(rgw_placement_rule)
+
+void encode_json(const char *name, const rgw_placement_rule& val, ceph::Formatter *f);
+void decode_json_obj(rgw_placement_rule& v, JSONObj *obj);
+
+inline ostream& operator<<(ostream& out, const rgw_placement_rule& rule) {
+  return out << rule.to_str();
+}
 struct RGWUserInfo
 {
   rgw_user user_id;
@@ -663,7 +755,7 @@ struct RGWUserInfo
   RGWUserCaps caps;
   __u8 admin;
   __u8 system;
-  string default_placement;
+  rgw_placement_rule default_placement;
   list<string> placement_tags;
   RGWQuotaInfo bucket_quota;
   map<int, string> temp_url_keys;
@@ -1266,7 +1358,7 @@ struct RGWBucketInfo {
   uint32_t flags;
   string zonegroup;
   ceph::real_time creation_time;
-  string placement_rule;
+  rgw_placement_rule placement_rule;
   bool has_instance_obj;
   RGWObjVersionTracker objv_tracker; /* we don't need to serialize this, for runtime tracking */
   obj_version ep_objv; /* entry point object version, for runtime tracking only */
@@ -1519,6 +1611,7 @@ struct req_info {
   string effective_uri;
   string request_params;
   string domain;
+  string storage_class;
 
   req_info(CephContext *cct, const RGWEnv *env);
   void rebuild_from(req_info& src);
@@ -1981,7 +2074,7 @@ struct RGWBucketEnt {
   /* The placement_rule is necessary to calculate per-storage-policy statics
    * of the Swift API. Although the info available in RGWBucketInfo, we need
    * to duplicate it here to not affect the performance of buckets listing. */
-  std::string placement_rule;
+  rgw_placement_rule placement_rule;
 
   RGWBucketEnt()
     : size(0),
@@ -2025,7 +2118,7 @@ struct RGWBucketEnt {
     ENCODE_FINISH(bl);
   }
   void decode(bufferlist::const_iterator& bl) {
-    DECODE_START_LEGACY_COMPAT_LEN(6, 5, 5, bl);
+    DECODE_START_LEGACY_COMPAT_LEN(7, 5, 5, bl);
     __u32 mt;
     uint64_t s;
     string empty_str;  // backward compatibility
index c9f50941111b5580b8a13c01ea5624eb8b155f63..448e6012f1f309a1d976c6a0666ed7b31d59a242 100644 (file)
@@ -54,6 +54,18 @@ void decode_json_obj(rgw_pool& pool, JSONObj *obj)
   pool = rgw_pool(s);
 }
 
+void encode_json(const char *name, const rgw_placement_rule& r, Formatter *f)
+{
+  encode_json(name, r.to_str(), f);
+}
+
+void decode_json_obj(rgw_placement_rule& v, JSONObj *obj)
+{
+  string s;
+  decode_json_obj(s, obj);
+  v.from_str(s);
+}
+
 void RGWOLHInfo::dump(Formatter *f) const
 {
   encode_json("target", target, f);
@@ -91,7 +103,7 @@ void rgw_bucket_placement::dump(Formatter *f) const
 
 void rgw_obj_select::dump(Formatter *f) const
 {
-  f->dump_string("placement_rule", placement_rule);
+  f->dump_string("placement_rule", placement_rule.to_str());
   f->dump_object("obj", obj);
   f->dump_object("raw_obj", raw_obj);
   f->dump_bool("is_raw", is_raw);
@@ -471,7 +483,8 @@ void RGWUserInfo::dump(Formatter *f) const
   if (system) { /* no need to show it for every user */
     encode_json("system", (bool)system, f);
   }
-  encode_json("default_placement", default_placement, f);
+  encode_json("default_placement", default_placement.name, f);
+  encode_json("default_storage_class", default_placement.get_storage_class(), f);
   encode_json("placement_tags", placement_tags, f);
   encode_json("bucket_quota", bucket_quota, f);
   encode_json("user_quota", user_quota, f);
@@ -548,7 +561,8 @@ void RGWUserInfo::decode_json(JSONObj *obj)
   bool sys = false;
   JSONDecoder::decode_json("system", sys, obj);
   system = (__u8)sys;
-  JSONDecoder::decode_json("default_placement", default_placement, obj);
+  JSONDecoder::decode_json("default_placement", default_placement.name, obj);
+  JSONDecoder::decode_json("default_storage_class", default_placement.storage_class, obj);
   JSONDecoder::decode_json("placement_tags", placement_tags, obj);
   JSONDecoder::decode_json("bucket_quota", bucket_quota, obj);
   JSONDecoder::decode_json("user_quota", user_quota, obj);
@@ -783,7 +797,9 @@ void RGWBucketInfo::decode_json(JSONObj *obj) {
   if (zonegroup.empty()) {
     JSONDecoder::decode_json("region", zonegroup, obj);
   }
-  JSONDecoder::decode_json("placement_rule", placement_rule, obj);
+  string pr;
+  JSONDecoder::decode_json("placement_rule", pr, obj);
+  placement_rule.from_str(pr);
   JSONDecoder::decode_json("has_instance_obj", has_instance_obj, obj);
   JSONDecoder::decode_json("quota", quota, obj);
   JSONDecoder::decode_json("num_shards", num_shards, obj);
@@ -828,7 +844,7 @@ void RGWBucketEnt::dump(Formatter *f) const
   utime_t ut(creation_time);
   encode_json("mtime", ut, f); /* mtime / creation time discrepency needed for backward compatibility */
   encode_json("count", count, f);
-  encode_json("placement_rule", placement_rule, f);
+  encode_json("placement_rule", placement_rule.to_str(), f);
 }
 
 void RGWUploadPartInfo::dump(Formatter *f) const
@@ -951,7 +967,7 @@ void RGWZoneParams::dump(Formatter *f) const
 void RGWZonePlacementInfo::dump(Formatter *f) const
 {
   encode_json("index_pool", index_pool, f);
-  encode_json("data_pool", data_pool, f);
+  encode_json("data_pools", data_pools, f);
   encode_json("data_extra_pool", data_extra_pool, f);
   encode_json("index_type", (uint32_t)index_type, f);
   encode_json("compression", compression_type, f);
@@ -960,7 +976,15 @@ void RGWZonePlacementInfo::dump(Formatter *f) const
 void RGWZonePlacementInfo::decode_json(JSONObj *obj)
 {
   JSONDecoder::decode_json("index_pool", index_pool, obj);
-  JSONDecoder::decode_json("data_pool", data_pool, obj);
+  JSONDecoder::decode_json("data_pools", data_pools, obj);
+  if (JSONDecoder::decode_json("data_pool", standard_data_pool, obj)) {
+    data_pools[RGW_STORAGE_CLASS_STANDARD] = standard_data_pool;
+  } else {
+    auto iter = data_pools.find(RGW_STORAGE_CLASS_STANDARD);
+    if (iter != data_pools.end()) {
+      standard_data_pool = iter->second;
+    }
+  }
   JSONDecoder::decode_json("data_extra_pool", data_extra_pool, obj);
   uint32_t it;
   JSONDecoder::decode_json("index_type", it, obj);
@@ -1029,12 +1053,17 @@ void RGWZoneGroupPlacementTarget::dump(Formatter *f) const
 {
   encode_json("name", name, f);
   encode_json("tags", tags, f);
+  encode_json("storage_classes", storage_classes, f);
 }
 
 void RGWZoneGroupPlacementTarget::decode_json(JSONObj *obj)
 {
   JSONDecoder::decode_json("name", name, obj);
   JSONDecoder::decode_json("tags", tags, obj);
+  JSONDecoder::decode_json("storage_classes", storage_classes, obj);
+  if (storage_classes.empty()) {
+    storage_classes.insert(RGW_STORAGE_CLASS_STANDARD);
+  }
 }
 
 void RGWZoneGroup::dump(Formatter *f) const
@@ -1083,7 +1112,8 @@ void RGWZoneGroup::decode_json(JSONObj *obj)
   JSONDecoder::decode_json("master_zone", master_zone, obj);
   JSONDecoder::decode_json("zones", zones, decode_zones, obj);
   JSONDecoder::decode_json("placement_targets", placement_targets, decode_placement_targets, obj);
-  JSONDecoder::decode_json("default_placement", default_placement, obj);
+  JSONDecoder::decode_json("default_placement", default_placement.name, obj);
+  JSONDecoder::decode_json("default_storage_class", default_placement.storage_class, obj);
   JSONDecoder::decode_json("realm_id", realm_id, obj);
 }
 
index 234aa3f607b4872ddee38d69ef6cadb330ee2157..6a7d0599524e46f39171147ff7ff123f12d366c9 100644 (file)
@@ -2086,7 +2086,7 @@ void RGWListBuckets::execute()
 
       /* operator[] still can create a new entry for storage policy seen
        * for first time. */
-      auto& policy_stats = policies_stats[bucket.placement_rule];
+      auto& policy_stats = policies_stats[bucket.placement_rule.to_str()];
       policy_stats.bytes_used += bucket.size;
       policy_stats.bytes_used_rounded += bucket.size_rounded;
       policy_stats.buckets_count++;
@@ -2228,7 +2228,7 @@ void RGWStatAccount::execute()
 
         /* operator[] still can create a new entry for storage policy seen
          * for first time. */
-        auto& policy_stats = policies_stats[bucket.placement_rule];
+        auto& policy_stats = policies_stats[bucket.placement_rule.to_str()];
         policy_stats.bytes_used += bucket.size;
         policy_stats.bytes_used_rounded += bucket.size_rounded;
         policy_stats.buckets_count++;
@@ -2833,9 +2833,9 @@ void RGWCreateBucket::execute()
   }
 
   const auto& zonegroup = store->svc.zone->get_zonegroup();
-  if (!placement_rule.empty() &&
-      !zonegroup.placement_targets.count(placement_rule)) {
-    ldpp_dout(this, 0) << "placement target (" << placement_rule << ")"
+  if (!placement_rule.name.empty() &&
+      !zonegroup.placement_targets.count(placement_rule.name)) {
+    ldpp_dout(this, 0) << "placement target (" << placement_rule.name << ")"
                      << " doesn't exist in the placement targets of zonegroup"
                      << " (" << store->svc.zone->get_zonegroup().api_name << ")" << dendl;
     op_ret = -ERR_INVALID_LOCATION_CONSTRAINT;
@@ -2902,7 +2902,7 @@ void RGWCreateBucket::execute()
   }
 
   if (s->bucket_exists) {
-    string selected_placement_rule;
+    rgw_placement_rule selected_placement_rule;
     rgw_bucket bucket;
     bucket.tenant = s->bucket_tenant;
     bucket.name = s->bucket_name;
@@ -3388,6 +3388,7 @@ int RGWPutObj::get_data(const off_t fst, const off_t lst, bufferlist& bl)
 static CompressorRef get_compressor_plugin(const req_state *s,
                                            const std::string& compression_type)
 {
+#warning FIXME different compression types per placement rule + storage_class
   if (compression_type != "random") {
     return Compressor::create(s->cct, compression_type);
   }
@@ -3864,7 +3865,7 @@ void RGWPostObj::execute()
       filter = encrypt.get();
     } else {
       const auto& compression_type = store->svc.zone->get_zone_params().get_compression_type(
-          s->bucket_info.placement_rule);
+          s->bucket_info.placement_rule.name);
       if (compression_type != "none") {
         plugin = Compressor::create(s->cct, compression_type);
         if (!plugin) {
@@ -6395,9 +6396,10 @@ int RGWBulkUploadOp::handle_dir(const boost::string_ref path)
   }
 
 
-  std::string placement_rule;
+  rgw_placement_rule placement_rule;
+  placement_rule.storage_class = s->info.storage_class;
   if (bucket_exists) {
-    std::string selected_placement_rule;
+    rgw_placement_rule selected_placement_rule;
     rgw_bucket bucket;
     bucket.tenant = s->bucket_tenant;
     bucket.name = s->bucket_name;
@@ -6584,8 +6586,9 @@ int RGWBulkUploadOp::handle_file(const boost::string_ref path,
   /* No filters by default. */
   DataProcessor *filter = &processor;
 
+#warning add storage_class compression
   const auto& compression_type = store->svc.zone->get_zone_params().get_compression_type(
-      binfo.placement_rule);
+      binfo.placement_rule.name);
   CompressorRef plugin;
   boost::optional<RGWPutObj_Compress> compressor;
   if (compression_type != "none") {
index c38f87cf93cc5c453edc68f5421e82f56f0dc331..25e8d3041f6a925bcb326c7c030c0f3e49edba60 100644 (file)
@@ -901,7 +901,7 @@ class RGWCreateBucket : public RGWOp {
 protected:
   RGWAccessControlPolicy policy;
   string location_constraint;
-  string placement_rule;
+  rgw_placement_rule placement_rule;
   RGWBucketInfo info;
   obj_version ep_objv;
   bool has_cors;
@@ -1199,7 +1199,7 @@ protected:
   uint32_t policy_rw_mask;
   RGWAccessControlPolicy policy;
   RGWCORSConfiguration cors_config;
-  string placement_rule;
+  rgw_placement_rule placement_rule;
   boost::optional<std::string> swift_ver_location;
 
 public:
index cb6948f43b0cbfdc65fba8d3dbbe84ee4abc1264..b7b6f809103ea55f8fffeab075ff6e1099e1768b 100644 (file)
@@ -114,7 +114,7 @@ class ManifestObjectProcessor : public HeadObjectProcessor,
  protected:
   RGWRados *const store;
   const RGWBucketInfo& bucket_info;
-  const string *ptail_placement_rule;
+  const rgw_placement_rule *ptail_placement_rule;
   const rgw_user& owner;
   RGWObjectCtx& obj_ctx;
   rgw_obj head_obj;
@@ -131,7 +131,7 @@ class ManifestObjectProcessor : public HeadObjectProcessor,
  public:
   ManifestObjectProcessor(Aio *aio, RGWRados *store,
                           const RGWBucketInfo& bucket_info,
-                          const string *ptail_placement_rule,
+                          const rgw_placement_rule *ptail_placement_rule,
                           const rgw_user& owner, RGWObjectCtx& obj_ctx,
                           const rgw_obj& head_obj)
     : HeadObjectProcessor(0),
@@ -155,7 +155,7 @@ class AtomicObjectProcessor : public ManifestObjectProcessor {
  public:
   AtomicObjectProcessor(Aio *aio, RGWRados *store,
                         const RGWBucketInfo& bucket_info,
-                        const string *ptail_placement_rule,
+                        const rgw_placement_rule *ptail_placement_rule,
                         const rgw_user& owner,
                         RGWObjectCtx& obj_ctx, const rgw_obj& head_obj,
                         std::optional<uint64_t> olh_epoch,
@@ -196,7 +196,7 @@ class MultipartObjectProcessor : public ManifestObjectProcessor {
  public:
   MultipartObjectProcessor(Aio *aio, RGWRados *store,
                            const RGWBucketInfo& bucket_info,
-                           const string *ptail_placement_rule,
+                           const rgw_placement_rule *ptail_placement_rule,
                            const rgw_user& owner, RGWObjectCtx& obj_ctx,
                            const rgw_obj& head_obj,
                            const std::string& upload_id, uint64_t part_num,
index 271354a928121a3a662baef58ff5b4a46bb55858..984c026d2a36d58f9eb5125de654734a97fe062c 100644 (file)
@@ -108,16 +108,18 @@ static RGWObjCategory main_category = RGWObjCategory::Main;
 
 
 static bool rgw_get_obj_data_pool(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params,
-                                  const string& placement_id, const rgw_obj& obj, rgw_pool *pool)
+                                  const rgw_placement_rule& head_placement_rule,
+                                  const rgw_obj& obj, rgw_pool *pool)
 {
-  if (!zone_params.get_head_data_pool(placement_id, obj, pool)) {
+  if (!zone_params.get_head_data_pool(head_placement_rule, obj, pool)) {
     RGWZonePlacementInfo placement;
-    if (!zone_params.get_placement(zonegroup.default_placement, &placement)) {
+    if (!zone_params.get_placement(zonegroup.default_placement.name, &placement)) {
       return false;
     }
 
     if (!obj.in_extra_data) {
-      *pool = placement.data_pool;
+#warning zonegroup default placement backward compatibility json decode/encode
+      *pool = placement.get_data_pool(zonegroup.default_placement.storage_class);
     } else {
       *pool = placement.get_data_extra_pool();
     }
@@ -127,11 +129,12 @@ static bool rgw_get_obj_data_pool(const RGWZoneGroup& zonegroup, const RGWZonePa
 }
 
 static bool rgw_obj_to_raw(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params,
-                           const string& placement_id, const rgw_obj& obj, rgw_raw_obj *raw_obj)
+                           const rgw_placement_rule& head_placement_rule,
+                           const rgw_obj& obj, rgw_raw_obj *raw_obj)
 {
   get_obj_bucket_and_oid_loc(obj, raw_obj->oid, raw_obj->loc);
 
-  return rgw_get_obj_data_pool(zonegroup, zone_params, placement_id, obj, &raw_obj->pool);
+  return rgw_get_obj_data_pool(zonegroup, zone_params, head_placement_rule, obj, &raw_obj->pool);
 }
 
 rgw_raw_obj rgw_obj_select::get_raw_obj(const RGWZoneGroup& zonegroup, const RGWZoneParams& zone_params) const
@@ -221,11 +224,6 @@ void RGWObjManifest::obj_iterator::operator++()
   if (manifest->explicit_objs) {
     ++explicit_iter;
 
-    if (explicit_iter == manifest->objs.end()) {
-      ofs = manifest->obj_size;
-      return;
-    }
-
     update_explicit_pos();
 
     update_location();
@@ -308,8 +306,8 @@ void RGWObjManifest::obj_iterator::operator++()
 }
 
 int RGWObjManifest::generator::create_begin(CephContext *cct, RGWObjManifest *_m,
-                                            const string& head_placement_rule,
-                                            const string *tail_placement_rule,
+                                            const rgw_placement_rule& head_placement_rule,
+                                            const rgw_placement_rule *tail_placement_rule,
                                             const rgw_bucket& _b, const rgw_obj& _obj)
 {
   manifest = _m;
@@ -1029,7 +1027,7 @@ int RGWRados::get_max_chunk_size(const rgw_pool& pool, uint64_t *max_chunk_size)
   return 0;
 }
 
-int RGWRados::get_max_chunk_size(const string& placement_rule, const rgw_obj& obj, uint64_t *max_chunk_size)
+int RGWRados::get_max_chunk_size(const rgw_placement_rule& placement_rule, const rgw_obj& obj, uint64_t *max_chunk_size)
 {
   rgw_pool pool;
   if (!get_obj_data_pool(placement_rule, obj, &pool)) {
@@ -1746,11 +1744,11 @@ int RGWRados::open_bucket_index_ctx(const RGWBucketInfo& bucket_info, librados::
   auto& zonegroup = svc.zone->get_zonegroup();
   auto& zone_params = svc.zone->get_zone_params();
 
-  const string *rule = &bucket_info.placement_rule;
+  const rgw_placement_rule *rule = &bucket_info.placement_rule;
   if (rule->empty()) {
     rule = &zonegroup.default_placement;
   }
-  auto iter = zone_params.placement_pools.find(*rule);
+  auto iter = zone_params.placement_pools.find(rule->name);
   if (iter == zone_params.placement_pools.end()) {
     ldout(cct, 0) << "could not find placement rule " << *rule << " within zonegroup " << dendl;
     return -EINVAL;
@@ -2781,7 +2779,7 @@ void RGWRados::create_bucket_id(string *bucket_id)
 
 int RGWRados::create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
                             const string& zonegroup_id,
-                            const string& placement_rule,
+                            const rgw_placement_rule& placement_rule,
                             const string& swift_ver_location,
                             const RGWQuotaInfo * pquota_info,
                            map<std::string, bufferlist>& attrs,
@@ -2794,13 +2792,13 @@ int RGWRados::create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
                            bool exclusive)
 {
 #define MAX_CREATE_RETRIES 20 /* need to bound retries */
-  string selected_placement_rule_name;
+  rgw_placement_rule selected_placement_rule;
   RGWZonePlacementInfo rule_info;
 
   for (int i = 0; i < MAX_CREATE_RETRIES; i++) {
     int ret = 0;
     ret = svc.zone->select_bucket_placement(owner, zonegroup_id, placement_rule,
-                                            &selected_placement_rule_name, &rule_info);
+                                            &selected_placement_rule, &rule_info);
     if (ret < 0)
       return ret;
 
@@ -2823,7 +2821,7 @@ int RGWRados::create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
     info.bucket = bucket;
     info.owner = owner.user_id;
     info.zonegroup = zonegroup_id;
-    info.placement_rule = selected_placement_rule_name;
+    info.placement_rule = selected_placement_rule;
     info.index_type = rule_info.index_type;
     info.swift_ver_location = swift_ver_location;
     info.swift_versioning = (!swift_ver_location.empty());
@@ -2898,7 +2896,7 @@ bool RGWRados::get_obj_data_pool(const string& placement_rule, const rgw_obj& ob
   return rgw_get_obj_data_pool(svc.zone->get_zonegroup(), svc.zone->get_zone_params(), placement_rule, obj, pool);
 }
 
-bool RGWRados::obj_to_raw(const string& placement_rule, const rgw_obj& obj, rgw_raw_obj *raw_obj)
+bool RGWRados::obj_to_raw(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj *raw_obj)
 {
   get_obj_bucket_and_oid_loc(obj, raw_obj->oid, raw_obj->loc);
 
@@ -4224,7 +4222,7 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx,
 
   rgw::AioThrottle aio(cct->_conf->rgw_put_obj_min_window_size);
   using namespace rgw::putobj;
-  string *ptail_rule{nullptr};
+  rgw_placement_rule *ptail_rule{nullptr};
 #warning FIXME ptail_rule
   AtomicObjectProcessor processor(&aio, this, dest_bucket_info, ptail_rule, user_id,
                                   obj_ctx, dest_obj, olh_epoch, tag);
@@ -4262,8 +4260,9 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx,
   boost::optional<RGWPutObj_Compress> compressor;
   CompressorRef plugin;
 
+#warning compression type
   const auto& compression_type = svc.zone->get_zone_params().get_compression_type(
-      dest_bucket_info.placement_rule);
+      dest_bucket_info.placement_rule.name);
   if (compression_type != "none") {
     plugin = Compressor::create(cct, compression_type);
     if (!plugin) {
@@ -4481,7 +4480,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx,
                rgw_obj& src_obj,
                RGWBucketInfo& dest_bucket_info,
                RGWBucketInfo& src_bucket_info,
-               const string *ptail_rule,
+               const rgw_placement_rule *ptail_rule,
                real_time *src_mtime,
                real_time *mtime,
                const real_time *mod_ptr,
@@ -4595,7 +4594,7 @@ int RGWRados::copy_obj(RGWObjectCtx& obj_ctx,
   rgw_pool src_pool;
   rgw_pool dest_pool;
 
-  const string *src_rule{nullptr};
+  const rgw_placement_rule *src_rule{nullptr};
 
   if (astate->has_manifest) {
     src_rule = &astate->manifest.get_tail_placement().placement_rule;
@@ -4764,7 +4763,7 @@ done_ret:
 
 int RGWRados::copy_obj_data(RGWObjectCtx& obj_ctx,
                RGWBucketInfo& dest_bucket_info,
-               const string *ptail_rule,
+               const rgw_placement_rule *ptail_rule,
               RGWRados::Object::Read& read_op, off_t end,
                const rgw_obj& dest_obj,
               real_time *mtime,
index bb7d9d5df0362747f0f625a49d095b791e27f1d6..172bd68747f0ef0e7271e01c532e4c78b60d49e5 100644 (file)
@@ -136,15 +136,16 @@ static inline bool rgw_raw_obj_to_obj(const rgw_bucket& bucket, const rgw_raw_ob
   return true;
 }
 
+
 struct rgw_bucket_placement {
-  string placement_rule;
+  rgw_placement_rule placement_rule;
   rgw_bucket bucket;
 
   void dump(Formatter *f) const;
 };
 
 class rgw_obj_select {
-  string placement_rule;
+  rgw_placement_rule placement_rule;
   rgw_obj obj;
   rgw_raw_obj raw_obj;
   bool is_raw;
@@ -178,7 +179,7 @@ public:
     return *this;
   }
 
-  void set_placement_rule(const string& rule) {
+  void set_placement_rule(const rgw_placement_rule& rule) {
     placement_rule = rule;
   }
   void dump(Formatter *f) const;
@@ -403,7 +404,7 @@ protected:
 
   rgw_obj obj;
   uint64_t head_size;
-  string head_placement_rule;
+  rgw_placement_rule head_placement_rule;
 
   uint64_t max_head_size;
   string prefix;
@@ -604,7 +605,7 @@ public:
     return (obj_size > head_size);
   }
 
-  void set_head(const string& placement_rule, const rgw_obj& _o, uint64_t _s) {
+  void set_head(const rgw_placement_rule& placement_rule, const rgw_obj& _o, uint64_t _s) {
     head_placement_rule = placement_rule;
     obj = _o;
     head_size = _s;
@@ -619,7 +620,7 @@ public:
     return obj;
   }
 
-  void set_tail_placement(const string& placement_rule, const rgw_bucket& _b) {
+  void set_tail_placement(const rgw_placement_rule& placement_rule, const rgw_bucket& _b) {
     tail_placement.placement_rule = placement_rule;
     tail_placement.bucket = _b;
   }
@@ -628,7 +629,7 @@ public:
     return tail_placement;
   }
 
-  const string& get_head_placement_rule() {
+  const rgw_placement_rule& get_head_placement_rule() {
     return head_placement_rule;
   }
 
@@ -808,8 +809,8 @@ public:
     generator() : manifest(NULL), last_ofs(0), cur_part_ofs(0), cur_part_id(0), 
                  cur_stripe(0), cur_stripe_size(0) {}
     int create_begin(CephContext *cct, RGWObjManifest *manifest,
-                     const string& head_placement_rule,
-                     const string *tail_placement_rule,
+                     const rgw_placement_rule& head_placement_rule,
+                     const rgw_placement_rule *tail_placement_rule,
                      const rgw_bucket& bucket,
                      const rgw_obj& obj);
 
@@ -1397,7 +1398,7 @@ public:
 
   int get_required_alignment(const rgw_pool& pool, uint64_t *alignment);
   int get_max_chunk_size(const rgw_pool& pool, uint64_t *max_chunk_size);
-  int get_max_chunk_size(const string& placement_rule, const rgw_obj& obj, uint64_t *max_chunk_size);
+  int get_max_chunk_size(const rgw_placement_rule& placement_rule, const rgw_obj& obj, uint64_t *max_chunk_size);
 
   uint32_t get_max_bucket_shards() {
     return rgw_shards_max();
@@ -1456,12 +1457,12 @@ public:
   int clean_bucket_index(RGWBucketInfo& bucket_info, int num_shards);
   void create_bucket_id(string *bucket_id);
 
-  bool get_obj_data_pool(const string& placement_rule, const rgw_obj& obj, rgw_pool *pool);
-  bool obj_to_raw(const string& placement_rule, const rgw_obj& obj, rgw_raw_obj *raw_obj);
+  bool get_obj_data_pool(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_pool *pool);
+  bool obj_to_raw(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj *raw_obj);
 
   int create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
                             const string& zonegroup_id,
-                            const string& placement_rule,
+                            const rgw_placement_rule& placement_rule,
                             const string& swift_ver_location,
                             const RGWQuotaInfo * pquota_info,
                             map<std::string,bufferlist>& attrs,
@@ -1938,7 +1939,7 @@ public:
                rgw_obj& src_obj,
                RGWBucketInfo& dest_bucket_info,
                RGWBucketInfo& src_bucket_info,
-               const string *ptail_rule,
+               const rgw_placement_rule *ptail_rule,
                ceph::real_time *src_mtime,
                ceph::real_time *mtime,
                const ceph::real_time *mod_ptr,
@@ -1960,7 +1961,7 @@ public:
 
   int copy_obj_data(RGWObjectCtx& obj_ctx,
                RGWBucketInfo& dest_bucket_info,
-               const string *ptail_rule,
+               const rgw_placement_rule *ptail_rule,
               RGWRados::Object::Read& read_op, off_t end,
                const rgw_obj& dest_obj,
               ceph::real_time *mtime,
index 0b0fbb8eaa8e9422801f27f8aff4b85650cf0e08..9b321b29f277ceb8bc9a846888ffe867ecbb6f52 100644 (file)
@@ -92,6 +92,7 @@ static const struct rgw_http_attr base_rgw_to_http_attrs[] = {
   { RGW_ATTR_CONTENT_ENC,       "Content-Encoding" },
   { RGW_ATTR_USER_MANIFEST,     "X-Object-Manifest" },
   { RGW_ATTR_X_ROBOTS_TAG ,     "X-Robots-Tag" },
+  { RGW_ATTR_STORAGE_CLASS ,    "X-Amz-Storage-Class" },
   /* RGW_ATTR_AMZ_WEBSITE_REDIRECT_LOCATION header depends on access mode:
    * S3 endpoint: x-amz-website-redirect-location
    * S3Website endpoint: Location
@@ -116,6 +117,7 @@ static const struct generic_attr generic_attrs[] = {
   { "HTTP_CONTENT_DISPOSITION", RGW_ATTR_CONTENT_DISP },
   { "HTTP_CONTENT_ENCODING",    RGW_ATTR_CONTENT_ENC },
   { "HTTP_X_ROBOTS_TAG",        RGW_ATTR_X_ROBOTS_TAG },
+  { "HTTP_X_AMZ_STORAGE_CLASS", RGW_ATTR_STORAGE_CLASS },
 };
 
 map<string, string> rgw_to_http_attrs;
index ed3a819af094e63fe00e4d7fa66e670efeb55633..a35a6a3be510017966c447d0afe834079bddd45a 100644 (file)
@@ -1241,7 +1241,7 @@ int RGWCreateBucket_ObjStore_S3::get_params()
 
   size_t pos = location_constraint.find(':');
   if (pos != string::npos) {
-    placement_rule = location_constraint.substr(pos + 1);
+    placement_rule.init(location_constraint.substr(pos + 1), s->info.storage_class);
     location_constraint = location_constraint.substr(0, pos);
   }
 
@@ -3435,6 +3435,11 @@ int RGWHandler_REST_S3::init(RGWRados *store, struct req_state *s,
     }
   }
 
+  const char *sc = s->info.env->get("HTTP_X_AMZ_STORAGE_CLASS");
+  if (sc) {
+    s->info.storage_class = sc;
+  }
+
   return RGWHandler_REST::init(store, s, cio);
 }
 
index 1fcbc801ec9b6623f938a481c944e05c54c7e983..702a435bd06394aeb87a2860022e2ebb16b1cb1f 100644 (file)
@@ -470,9 +470,10 @@ static void dump_container_metadata(struct req_state *s,
     if (write_acl.size()) {
       dump_header(s, "X-Container-Write", write_acl);
     }
-    if (!s->bucket_info.placement_rule.empty()) {
-      dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule);
+    if (!s->bucket_info.placement_rule.name.empty()) {
+      dump_header(s, "X-Storage-Policy", s->bucket_info.placement_rule.name);
     }
+    dump_header(s, "X-Storage-Class", s->bucket_info.placement_rule.get_storage_class());
 
     /* Dump user-defined metadata items and generic attrs. */
     const size_t PREFIX_LEN = sizeof(RGW_ATTR_META_PREFIX) - 1;
@@ -710,7 +711,7 @@ int RGWCreateBucket_ObjStore_SWIFT::get_params()
   location_constraint = store->svc.zone->get_zonegroup().api_name;
   get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX,
                            CONT_REMOVE_ATTR_PREFIX, rmattr_names);
-  placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+  placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
 
   return get_swift_versioning_settings(s, swift_ver_location);
 }
@@ -1124,7 +1125,7 @@ int RGWPutMetadataBucket_ObjStore_SWIFT::get_params()
 
   get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX, CONT_REMOVE_ATTR_PREFIX,
                           rmattr_names);
-  placement_rule = s->info.env->get("HTTP_X_STORAGE_POLICY", "");
+  placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
 
   return get_swift_versioning_settings(s, swift_ver_location);
 }
@@ -1906,7 +1907,7 @@ void RGWInfo_ObjStore_SWIFT::list_swift_data(Formatter& formatter,
 
   for (const auto& placement_targets : zonegroup.placement_targets) {
     formatter.open_object_section("policy");
-    if (placement_targets.second.name.compare(zonegroup.default_placement) == 0)
+    if (placement_targets.second.name.compare(zonegroup.default_placement.name) == 0)
       formatter.dump_bool("default", true);
     formatter.dump_string("name", placement_targets.second.name.c_str());
     formatter.close_section();
@@ -3049,6 +3050,8 @@ int RGWHandler_REST_SWIFT::init(RGWRados* store, struct req_state* s,
     s->op = OP_PUT;
   }
 
+  s->info.storage_class = s->info.env->get("HTTP_X_OBJECT_STORAGE_CLASS", "");
+
   return RGWHandler_REST::init(store, s, cio);
 }
 
index 29b3984d36ea2ab6e454902417226a911ef6ffb0..e8acf3078070c660a10f887b0e68b4f8081cff43 100644 (file)
@@ -76,7 +76,7 @@ int RGWZoneGroup::create_default(bool old_format)
   RGWZoneGroupPlacementTarget placement_target;
   placement_target.name = "default-placement";
   placement_targets[placement_target.name] = placement_target;
-  default_placement = "default-placement";
+  default_placement.name = "default-placement";
 
   RGWZoneParams zone_params(default_zone_name);
 
@@ -290,7 +290,7 @@ void RGWZoneGroup::post_process_params()
   }
 
   if (default_placement.empty() && !placement_targets.empty()) {
-    default_placement = placement_targets.begin()->first;
+    default_placement.init(placement_targets.begin()->first, RGW_STORAGE_CLASS_STANDARD);
   }
 }
 
@@ -1547,7 +1547,9 @@ int get_zones_pool_set(CephContext* cct,
       pool_names.insert(zone.reshard_pool);
       for(auto& iter : zone.placement_pools) {
        pool_names.insert(iter.second.index_pool);
-       pool_names.insert(iter.second.data_pool);
+        for (auto& pi : iter.second.data_pools) {
+          pool_names.insert(pi.second);
+        }
        pool_names.insert(iter.second.data_extra_pool);
       }
     }
@@ -1621,8 +1623,10 @@ int RGWZoneParams::fix_pool_names()
   for(auto& iter : placement_pools) {
     iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix,
                                                iter.second.index_pool);
-    iter.second.data_pool = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
-                                              iter.second.data_pool);
+    for (auto& pi : iter.second.data_pools) {
+      pi.second = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
+                                                pi.second);
+    }
     iter.second.data_extra_pool= fix_zone_pool_dup(pools, name, "." + default_storage_extra_pool_suffix,
                                                    iter.second.data_extra_pool);
   }
@@ -1642,7 +1646,7 @@ int RGWZoneParams::create(bool exclusive)
     /* a new system, let's set new placement info */
     RGWZonePlacementInfo default_placement;
     default_placement.index_pool = name + "." + default_bucket_index_pool_suffix;
-    default_placement.data_pool =  name + "." + default_storage_pool_suffix;
+    default_placement.data_pools[RGW_STORAGE_CLASS_STANDARD] =  name + "." + default_storage_pool_suffix;
     default_placement.data_extra_pool = name + "." + default_storage_extra_pool_suffix;
     placement_pools["default-placement"] = default_placement;
   }
index 0a74479576fb55b43db3f46d425018971fdd3316..d50e69dcb719d9a26dec5521e893475ec66b1e4b 100644 (file)
@@ -153,15 +153,16 @@ WRITE_CLASS_ENCODER(RGWSystemMetaObj)
 
 struct RGWZonePlacementInfo {
   rgw_pool index_pool;
-  rgw_pool data_pool;
+  rgw_pool standard_data_pool;
   rgw_pool data_extra_pool; /* if not set we should use data_pool */
+  map<string, rgw_pool> data_pools;
   RGWBucketIndexType index_type;
   std::string compression_type;
 
   RGWZonePlacementInfo() : index_type(RGWBIType_Normal) {}
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(6, 1, bl);
+    ENCODE_START(7, 1, bl);
     encode(index_pool.to_str(), bl);
     encode(data_pool.to_str(), bl);
     encode(data_extra_pool.to_str(), bl);
@@ -356,7 +357,7 @@ struct RGWZoneParams : RGWSystemMetaObj {
   /*
    * return data pool of the head object
    */
-  bool get_head_data_pool(const std::string& placement_id, const rgw_obj& obj, rgw_pool *pool) const {
+  bool get_head_data_pool(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_pool *pool) const {
     const rgw_data_placement_target& explicit_placement = obj.bucket.explicit_placement;
     if (!explicit_placement.data_pool.empty()) {
       if (!obj.in_extra_data) {
@@ -366,15 +367,15 @@ struct RGWZoneParams : RGWSystemMetaObj {
       }
       return true;
     }
-    if (placement_id.empty()) {
+    if (placement_rule.empty()) {
       return false;
     }
-    auto iter = placement_pools.find(placement_id);
+    auto iter = placement_pools.find(placement_rule.name);
     if (iter == placement_pools.end()) {
       return false;
     }
     if (!obj.in_extra_data) {
-      *pool = iter->second.data_pool;
+      *pool = iter->second.get_data_pool(placement_rule.storage_class);
     } else {
       *pool = iter->second.get_data_extra_pool();
     }
@@ -490,6 +491,7 @@ WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo)
 struct RGWZoneGroupPlacementTarget {
   std::string name;
   set<std::string> tags;
+  set<std::string> storage_classes;
 
   bool user_permitted(const list<std::string>& user_tags) const {
     if (tags.empty()) {
@@ -504,16 +506,23 @@ struct RGWZoneGroupPlacementTarget {
   }
 
   void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
+    ENCODE_START(2, 1, bl);
     encode(name, bl);
     encode(tags, bl);
+    encode(storage_classes, bl);
     ENCODE_FINISH(bl);
   }
 
   void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
+    DECODE_START(2, bl);
     decode(name, bl);
     decode(tags, bl);
+    if (struct_v >= 2) {
+      decode(storage_classes, bl);
+    }
+    if (storage_classes.empty()) {
+      storage_classes.insert(RGW_STORAGE_CLASS_STANDARD);
+    }
     DECODE_FINISH(bl);
   }
   void dump(Formatter *f) const;
@@ -521,7 +530,6 @@ struct RGWZoneGroupPlacementTarget {
 };
 WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTarget)
 
-
 struct RGWZoneGroup : public RGWSystemMetaObj {
   std::string api_name;
   list<std::string> endpoints;
@@ -531,7 +539,7 @@ struct RGWZoneGroup : public RGWSystemMetaObj {
   map<std::string, RGWZone> zones;
 
   map<std::string, RGWZoneGroupPlacementTarget> placement_targets;
-  std::string default_placement;
+  rgw_placement_rule default_placement;
 
   list<std::string> hostnames;
   list<std::string> hostnames_s3website;
index ea6518427f553feb4ebcdf96b3ece1c1e79794a8..d6717ef08f7fb50df6ac8e0cc72d7d7d5598af27 100644 (file)
@@ -942,9 +942,9 @@ bool RGWSI_Zone::is_syncing_bucket_meta(const rgw_bucket& bucket)
 }
 
 
-int RGWSI_Zone::select_new_bucket_location(const RGWUserInfo& user_info, const string& zonegroup_id, const string& request_rule,
-                                         string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
-
+int RGWSI_Zone::select_new_bucket_location(const RGWUserInfo& user_info, const string& zonegroup_id,
+                                         const rgw_placement_rule& request_rule,
+                                         rgw_placement_rule *pselected_rule_name, RGWZonePlacementInfo *rule_info)
 {
   /* first check that zonegroup exists within current period. */
   RGWZoneGroup zonegroup;
@@ -954,29 +954,34 @@ int RGWSI_Zone::select_new_bucket_location(const RGWUserInfo& user_info, const s
     return ret;
   }
 
+  const rgw_placement_rule *used_rule;
+
   /* find placement rule. Hierarchy: request rule > user default rule > zonegroup default rule */
   std::map<std::string, RGWZoneGroupPlacementTarget>::const_iterator titer;
 
-  if (!request_rule.empty()) {
-    titer = zonegroup.placement_targets.find(request_rule);
+  if (!request_rule.name.empty()) {
+    used_rule = &request_rule;
+    titer = zonegroup.placement_targets.find(request_rule.name);
     if (titer == zonegroup.placement_targets.end()) {
       ldout(cct, 0) << "could not find requested placement id " << request_rule 
                     << " within zonegroup " << dendl;
       return -ERR_INVALID_LOCATION_CONSTRAINT;
     }
   } else if (!user_info.default_placement.empty()) {
-    titer = zonegroup.placement_targets.find(user_info.default_placement);
+    used_rule = &user_info.default_placement;
+    titer = zonegroup.placement_targets.find(user_info.default_placement.name);
     if (titer == zonegroup.placement_targets.end()) {
       ldout(cct, 0) << "could not find user default placement id " << user_info.default_placement
                     << " within zonegroup " << dendl;
       return -ERR_INVALID_LOCATION_CONSTRAINT;
     }
   } else {
-    if (zonegroup.default_placement.empty()) { // zonegroup default rule as fallback, it should not be empty.
+    if (zonegroup.default_placement.name.empty()) { // zonegroup default rule as fallback, it should not be empty.
       ldout(cct, 0) << "misconfiguration, zonegroup default placement id should not be empty." << dendl;
       return -ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION;
     } else {
-      titer = zonegroup.placement_targets.find(zonegroup.default_placement);
+      used_rule = &zonegroup.default_placement;
+      titer = zonegroup.placement_targets.find(zonegroup.default_placement.name);
       if (titer == zonegroup.placement_targets.end()) {
         ldout(cct, 0) << "could not find zonegroup default placement id " << zonegroup.default_placement
                       << " within zonegroup " << dendl;
@@ -992,15 +997,24 @@ int RGWSI_Zone::select_new_bucket_location(const RGWUserInfo& user_info, const s
     return -EPERM;
   }
 
-  if (pselected_rule_name)
-    *pselected_rule_name = titer->first;
+  const string *storage_class = &request_rule.storage_class;
+
+  if (storage_class->empty()) {
+    storage_class = &used_rule->storage_class;
+  }
+
+  rgw_placement_rule rule(titer->first, *storage_class);
 
-  return select_bucket_location_by_rule(titer->first, rule_info);
+  if (pselected_rule_name) {
+    *pselected_rule_name = rule;
+  }
+
+  return select_bucket_location_by_rule(rule, rule_info);
 }
 
-int RGWSI_Zone::select_bucket_location_by_rule(const string& location_rule, RGWZonePlacementInfo *rule_info)
+int RGWSI_Zone::select_bucket_location_by_rule(const rgw_placement_rule& location_rule, RGWZonePlacementInfo *rule_info)
 {
-  if (location_rule.empty()) {
+  if (location_rule.name.empty()) {
     /* we can only reach here if we're trying to set a bucket location from a bucket
      * created on a different zone, using a legacy / default pool configuration
      */
@@ -1016,7 +1030,7 @@ int RGWSI_Zone::select_bucket_location_by_rule(const string& location_rule, RGWZ
    * checking it for the local zone, because that's where this bucket object is going to
    * reside.
    */
-  auto piter = zone_params->placement_pools.find(location_rule);
+  auto piter = zone_params->placement_pools.find(location_rule.name);
   if (piter == zone_params->placement_pools.end()) {
     /* couldn't find, means we cannot really place data for this bucket in this zone */
     ldout(cct, 0) << "ERROR: This zone does not contain placement rule "
@@ -1024,6 +1038,8 @@ int RGWSI_Zone::select_bucket_location_by_rule(const string& location_rule, RGWZ
     return -EINVAL;
   }
 
+#warning FIXME check that location_rule.storage_class exists in piter->second
+
   RGWZonePlacementInfo& placement_info = piter->second;
 
   if (rule_info) {
@@ -1033,16 +1049,17 @@ int RGWSI_Zone::select_bucket_location_by_rule(const string& location_rule, RGWZ
   return 0;
 }
 
-int RGWSI_Zone::select_bucket_placement(const RGWUserInfo& user_info, const string& zonegroup_id, const string& placement_rule,
-                                      string *pselected_rule_name, RGWZonePlacementInfo *rule_info)
+int RGWSI_Zone::select_bucket_placement(const RGWUserInfo& user_info, const string& zonegroup_id,
+                                        const rgw_placement_rule& placement_rule,
+                                        rgw_placement_rule *pselected_rule, RGWZonePlacementInfo *rule_info)
 {
   if (!zone_params->placement_pools.empty()) {
     return select_new_bucket_location(user_info, zonegroup_id, placement_rule,
-                                      pselected_rule_name, rule_info);
+                                      pselected_rule, rule_info);
   }
 
-  if (pselected_rule_name) {
-    pselected_rule_name->clear();
+  if (pselected_rule) {
+    pselected_rule->clear();
   }
 
   if (rule_info) {
@@ -1115,7 +1132,7 @@ read_omap:
   }
   pool_name = miter->first;
 
-  rule_info->data_pool = pool_name;
+  rule_info->data_pools[RGW_STORAGE_CLASS_STANDARD] = pool_name;
   rule_info->data_extra_pool = pool_name;
   rule_info->index_pool = pool_name;
   rule_info->index_type = RGWBIType_Normal;
index 8884ccb2293b7b4d855e8e63849c6427756959e2..d2900fcc450c2abf3877cd7b95e08b0d175a1974 100644 (file)
@@ -103,12 +103,14 @@ public:
   RGWRESTConn *get_zone_conn_by_name(const string& name);
   bool find_zone_id_by_name(const string& name, string *id);
 
-  int select_bucket_placement(const RGWUserInfo& user_info, const string& zonegroup_id, const string& rule,
-                              string *pselected_rule_name, RGWZonePlacementInfo *rule_info);
+  int select_bucket_placement(const RGWUserInfo& user_info, const string& zonegroup_id,
+                              const rgw_placement_rule& rule,
+                              rgw_placement_rule *pselected_rule, RGWZonePlacementInfo *rule_info);
   int select_legacy_bucket_placement(RGWZonePlacementInfo *rule_info);
-  int select_new_bucket_location(const RGWUserInfo& user_info, const string& zonegroup_id, const string& rule,
-                                 string *pselected_rule_name, RGWZonePlacementInfo *rule_info);
-  int select_bucket_location_by_rule(const string& location_rule, RGWZonePlacementInfo *rule_info);
+  int select_new_bucket_location(const RGWUserInfo& user_info, const string& zonegroup_id,
+                                 const rgw_placement_rule& rule,
+                                 rgw_placement_rule *pselected_rule_name, RGWZonePlacementInfo *rule_info);
+  int select_bucket_location_by_rule(const rgw_placement_rule& location_rule, RGWZonePlacementInfo *rule_info);
 
   int add_bucket_placement(const rgw_pool& new_pool);
   int remove_bucket_placement(const rgw_pool& old_pool);