From: Yehuda Sadeh Date: Fri, 15 Jun 2018 01:17:01 +0000 (-0700) Subject: rgw: add support for storage class X-Git-Tag: v14.1.0~314^2~57 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5e4201daba625887311c2ff60deb8ac7b5d61f43;p=ceph.git rgw: add support for storage class Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index f28ccf997285..d056c0287015 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -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 of tags for zonegroup placement add and modify commands\n"; cout << " --tags-add= list of tags to add for zonegroup placement modify command\n"; cout << " --tags-rm= 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 tags; list tags_add; list 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; diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 19c534f381f2..3ff965ec510d 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -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); diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 146074540877..26ee460390dc 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -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 placement_tags; RGWQuotaInfo bucket_quota; map 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 diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc index c9f50941111b..448e6012f1f3 100644 --- a/src/rgw/rgw_json_enc.cc +++ b/src/rgw/rgw_json_enc.cc @@ -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); } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 234aa3f607b4..6a7d0599524e 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -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 compressor; if (compression_type != "none") { diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index c38f87cf93cc..25e8d3041f6a 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -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 swift_ver_location; public: diff --git a/src/rgw/rgw_putobj_processor.h b/src/rgw/rgw_putobj_processor.h index cb6948f43b0c..b7b6f809103e 100644 --- a/src/rgw/rgw_putobj_processor.h +++ b/src/rgw/rgw_putobj_processor.h @@ -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 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, diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 271354a92812..984c026d2a36 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -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& 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 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, diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index bb7d9d5df036..172bd68747f0 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -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& 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, diff --git a/src/rgw/rgw_rest.cc b/src/rgw/rgw_rest.cc index 0b0fbb8eaa8e..9b321b29f277 100644 --- a/src/rgw/rgw_rest.cc +++ b/src/rgw/rgw_rest.cc @@ -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 rgw_to_http_attrs; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index ed3a819af094..a35a6a3be510 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -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); } diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 1fcbc801ec9b..702a435bd063 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -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); } diff --git a/src/rgw/rgw_zone.cc b/src/rgw/rgw_zone.cc index 29b3984d36ea..e8acf3078070 100644 --- a/src/rgw/rgw_zone.cc +++ b/src/rgw/rgw_zone.cc @@ -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; } diff --git a/src/rgw/rgw_zone.h b/src/rgw/rgw_zone.h index 0a74479576fb..d50e69dcb719 100644 --- a/src/rgw/rgw_zone.h +++ b/src/rgw/rgw_zone.h @@ -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 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 tags; + set storage_classes; bool user_permitted(const list& 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 endpoints; @@ -531,7 +539,7 @@ struct RGWZoneGroup : public RGWSystemMetaObj { map zones; map placement_targets; - std::string default_placement; + rgw_placement_rule default_placement; list hostnames; list hostnames_s3website; diff --git a/src/rgw/services/svc_zone.cc b/src/rgw/services/svc_zone.cc index ea6518427f55..d6717ef08f7f 100644 --- a/src/rgw/services/svc_zone.cc +++ b/src/rgw/services/svc_zone.cc @@ -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::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; diff --git a/src/rgw/services/svc_zone.h b/src/rgw/services/svc_zone.h index 8884ccb2293b..d2900fcc450c 100644 --- a/src/rgw/services/svc_zone.h +++ b/src/rgw/services/svc_zone.h @@ -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);