// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab ft=cpp /* * Ceph - scalable distributed file system * * Copyright (C) 2019 Red Hat, Inc. * * This is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software * Foundation. See file COPYING. * */ /* N.B., this header defines fundamental serialized types. Do not * introduce changes or include files which can only be compiled in * radosgw or OSD contexts (e.g., rgw_sal.h, rgw_common.h) */ #pragma once #include #include #include #include #include #include #include "include/types.h" #include "rgw_bucket_layout.h" #include "rgw_zone_features.h" #include "rgw_pool_types.h" #include "rgw_acl_types.h" #include "rgw_placement_types.h" #include "common/Formatter.h" class JSONObj; namespace rgw_zone_defaults { extern std::string zone_names_oid_prefix; extern std::string region_info_oid_prefix; extern std::string realm_names_oid_prefix; extern std::string zone_group_info_oid_prefix; extern std::string realm_info_oid_prefix; extern std::string default_region_info_oid; extern std::string default_zone_group_info_oid; extern std::string region_map_oid; extern std::string default_realm_info_oid; extern std::string default_zonegroup_name; extern std::string default_zone_name; extern std::string zonegroup_names_oid_prefix; extern std::string RGW_DEFAULT_ZONE_ROOT_POOL; extern std::string RGW_DEFAULT_ZONEGROUP_ROOT_POOL; extern std::string RGW_DEFAULT_REALM_ROOT_POOL; extern std::string RGW_DEFAULT_PERIOD_ROOT_POOL; extern std::string avail_pools; extern std::string default_storage_pool_suffix; } /* namespace rgw_zone_defaults */ struct RGWNameToId { std::string obj_id; void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(obj_id, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(obj_id, bl); DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWNameToId) struct RGWDefaultSystemMetaObjInfo { std::string default_id; void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(default_id, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(default_id, bl); DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWDefaultSystemMetaObjInfo) struct RGWZoneStorageClass { boost::optional data_pool; boost::optional compression_type; void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(data_pool, bl); encode(compression_type, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(data_pool, bl); decode(compression_type, bl); DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWZoneStorageClass) class RGWZoneStorageClasses { std::map m; /* in memory only */ RGWZoneStorageClass *standard_class; public: RGWZoneStorageClasses() { standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; } RGWZoneStorageClasses(const RGWZoneStorageClasses& rhs) { m = rhs.m; standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; } RGWZoneStorageClasses& operator=(const RGWZoneStorageClasses& rhs) { m = rhs.m; standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; return *this; } const RGWZoneStorageClass& get_standard() const { return *standard_class; } bool find(const std::string& sc, const RGWZoneStorageClass** pstorage_class) const { auto iter = m.find(sc); if (iter == m.end()) { return false; } *pstorage_class = &iter->second; return true; } bool exists(const std::string& sc) const { if (sc.empty()) { return true; } auto iter = m.find(sc); return (iter != m.end()); } const std::map& get_all() const { return m; } std::map& get_all() { return m; } void set_storage_class(const std::string& sc, const rgw_pool* data_pool, const std::string* compression_type) { const std::string *psc = ≻ if (sc.empty()) { psc = &RGW_STORAGE_CLASS_STANDARD; } RGWZoneStorageClass& storage_class = m[*psc]; if (data_pool) { storage_class.data_pool = *data_pool; } if (compression_type) { storage_class.compression_type = *compression_type; } } void remove_storage_class(const std::string& sc) { if (!sc.empty()) { m.erase(sc); } } void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(m, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(m, bl); standard_class = &m[RGW_STORAGE_CLASS_STANDARD]; DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWZoneStorageClasses) struct RGWZonePlacementInfo { rgw_pool index_pool; rgw_pool data_extra_pool; /* if not set we should use data_pool */ RGWZoneStorageClasses storage_classes; rgw::BucketIndexType index_type; bool inline_data; RGWZonePlacementInfo() : index_type(rgw::BucketIndexType::Normal), inline_data(true) {} void encode(bufferlist& bl) const { ENCODE_START(8, 1, bl); encode(index_pool.to_str(), bl); rgw_pool standard_data_pool = get_data_pool(RGW_STORAGE_CLASS_STANDARD); encode(standard_data_pool.to_str(), bl); encode(data_extra_pool.to_str(), bl); encode((uint32_t)index_type, bl); std::string standard_compression_type = get_compression_type(RGW_STORAGE_CLASS_STANDARD); encode(standard_compression_type, bl); encode(storage_classes, bl); encode(inline_data, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(8, bl); std::string index_pool_str; std::string data_pool_str; decode(index_pool_str, bl); index_pool = rgw_pool(index_pool_str); decode(data_pool_str, bl); rgw_pool standard_data_pool(data_pool_str); if (struct_v >= 4) { std::string data_extra_pool_str; decode(data_extra_pool_str, bl); data_extra_pool = rgw_pool(data_extra_pool_str); } if (struct_v >= 5) { uint32_t it; decode(it, bl); index_type = (rgw::BucketIndexType)it; } std::string standard_compression_type; if (struct_v >= 6) { decode(standard_compression_type, bl); } if (struct_v >= 7) { decode(storage_classes, bl); } else { storage_classes.set_storage_class(RGW_STORAGE_CLASS_STANDARD, &standard_data_pool, (!standard_compression_type.empty() ? &standard_compression_type : nullptr)); } if (struct_v >= 8) { decode(inline_data, bl); } DECODE_FINISH(bl); } const rgw_pool& get_data_extra_pool() const { static rgw_pool no_pool; if (data_extra_pool.empty()) { return storage_classes.get_standard().data_pool.get_value_or(no_pool); } return data_extra_pool; } const rgw_pool& get_data_pool(const std::string& sc) const { const RGWZoneStorageClass *storage_class; static rgw_pool no_pool; if (!storage_classes.find(sc, &storage_class)) { return storage_classes.get_standard().data_pool.get_value_or(no_pool); } return storage_class->data_pool.get_value_or(no_pool); } const rgw_pool& get_standard_data_pool() const { return get_data_pool(RGW_STORAGE_CLASS_STANDARD); } const std::string& get_compression_type(const std::string& sc) const { const RGWZoneStorageClass *storage_class; static std::string no_compression; if (!storage_classes.find(sc, &storage_class)) { return no_compression; } return storage_class->compression_type.get_value_or(no_compression); } bool storage_class_exists(const std::string& sc) const { return storage_classes.exists(sc); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWZonePlacementInfo) struct RGWZone { std::string id; std::string name; std::list endpoints; // std::vector? bool log_meta; bool log_data; bool read_only; std::string tier_type; std::string redirect_zone; /** * Represents the number of shards for the bucket index object, a value of zero * indicates there is no sharding. By default (no sharding, the name of the object * is '.dir.{marker}', with sharding, the name is '.dir.{marker}.{sharding_id}', * sharding_id is zero-based value. It is not recommended to set a too large value * (e.g. thousand) as it increases the cost for bucket listing. */ uint32_t bucket_index_max_shards; // pre-shard buckets on creation to enable some write-parallism by default, // delay the need to reshard as the bucket grows, and (in multisite) get some // bucket index sharding where dynamic resharding is not supported static constexpr uint32_t default_bucket_index_max_shards = 11; bool sync_from_all; std::set sync_from; /* list of zones to sync from */ rgw::zone_features::set supported_features; RGWZone() : log_meta(false), log_data(false), read_only(false), bucket_index_max_shards(default_bucket_index_max_shards), sync_from_all(true) {} void encode(bufferlist& bl) const { ENCODE_START(8, 1, bl); encode(name, bl); encode(endpoints, bl); encode(log_meta, bl); encode(log_data, bl); encode(bucket_index_max_shards, bl); encode(id, bl); encode(read_only, bl); encode(tier_type, bl); encode(sync_from_all, bl); encode(sync_from, bl); encode(redirect_zone, bl); encode(supported_features, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(8, bl); decode(name, bl); if (struct_v < 4) { id = name; } decode(endpoints, bl); if (struct_v >= 2) { decode(log_meta, bl); decode(log_data, bl); } if (struct_v >= 3) { decode(bucket_index_max_shards, bl); } if (struct_v >= 4) { decode(id, bl); decode(read_only, bl); } if (struct_v >= 5) { decode(tier_type, bl); } if (struct_v >= 6) { decode(sync_from_all, bl); decode(sync_from, bl); } if (struct_v >= 7) { decode(redirect_zone, bl); } if (struct_v >= 8) { decode(supported_features, bl); } DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); static void generate_test_instances(std::list& o); bool is_read_only() const { return read_only; } bool syncs_from(const std::string& zone_name) const { return (sync_from_all || sync_from.find(zone_name) != sync_from.end()); } bool supports(std::string_view feature) const { return supported_features.contains(feature); } }; WRITE_CLASS_ENCODER(RGWZone) struct RGWDefaultZoneGroupInfo { std::string default_zonegroup; void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(default_zonegroup, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(default_zonegroup, bl); DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); //todo: implement ceph-dencoder }; WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo) struct RGWTierACLMapping { ACLGranteeTypeEnum type{ACL_TYPE_CANON_USER}; std::string source_id; std::string dest_id; RGWTierACLMapping() = default; RGWTierACLMapping(ACLGranteeTypeEnum t, const std::string& s, const std::string& d) : type(t), source_id(s), dest_id(d) {} void init(const JSONFormattable& config) { const std::string& t = config["type"]; if (t == "email") { type = ACL_TYPE_EMAIL_USER; } else if (t == "uri") { type = ACL_TYPE_GROUP; } else { type = ACL_TYPE_CANON_USER; } source_id = config["source_id"]; dest_id = config["dest_id"]; } void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode((uint32_t)type, bl); encode(source_id, bl); encode(dest_id, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); uint32_t it; decode(it, bl); type = (ACLGranteeTypeEnum)it; decode(source_id, bl); decode(dest_id, bl); DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWTierACLMapping) enum HostStyle { PathStyle = 0, VirtualStyle = 1, }; struct RGWZoneGroupPlacementTierS3 { #define DEFAULT_MULTIPART_SYNC_PART_SIZE (32 * 1024 * 1024) std::string endpoint; RGWAccessKey key; std::string region; HostStyle host_style{PathStyle}; std::string target_storage_class; /* Should below be bucket/zone specific?? */ std::string target_path; std::map acl_mappings; uint64_t multipart_sync_threshold{DEFAULT_MULTIPART_SYNC_PART_SIZE}; uint64_t multipart_min_part_size{DEFAULT_MULTIPART_SYNC_PART_SIZE}; int update_params(const JSONFormattable& config); int clear_params(const JSONFormattable& config); void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(endpoint, bl); encode(key, bl); encode(region, bl); encode((uint32_t)host_style, bl); // XXX kill C-style casts encode(target_storage_class, bl); encode(target_path, bl); encode(acl_mappings, bl); encode(multipart_sync_threshold, bl); encode(multipart_min_part_size, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(endpoint, bl); decode(key, bl); decode(region, bl); uint32_t it; decode(it, bl); host_style = (HostStyle)it; // XXX can't this be HostStyle(it)? decode(target_storage_class, bl); decode(target_path, bl); decode(acl_mappings, bl); decode(multipart_sync_threshold, bl); decode(multipart_min_part_size, bl); DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTierS3) struct RGWZoneGroupPlacementTier { std::string tier_type; std::string storage_class; bool retain_head_object = false; struct _tier { RGWZoneGroupPlacementTierS3 s3; } t; int update_params(const JSONFormattable& config); int clear_params(const JSONFormattable& config); void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); encode(tier_type, bl); encode(storage_class, bl); encode(retain_head_object, bl); if (tier_type == "cloud-s3") { encode(t.s3, bl); } ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(1, bl); decode(tier_type, bl); decode(storage_class, bl); decode(retain_head_object, bl); if (tier_type == "cloud-s3") { decode(t.s3, bl); } DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTier) struct RGWZoneGroupPlacementTarget { std::string name; std::set tags; std::set storage_classes; std::map tier_targets; bool user_permitted(const std::list& user_tags) const { if (tags.empty()) { return true; } for (auto& rule : user_tags) { if (tags.find(rule) != tags.end()) { return true; } } return false; } void encode(bufferlist& bl) const { ENCODE_START(3, 1, bl); encode(name, bl); encode(tags, bl); encode(storage_classes, bl); encode(tier_targets, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { DECODE_START(3, 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); } if (struct_v >= 3) { decode(tier_targets, bl); } DECODE_FINISH(bl); } void dump(Formatter *f) const; void decode_json(JSONObj *obj); }; WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTarget)