From 71799fb6f300a746abaa43b9090fe4ccdf130061 Mon Sep 17 00:00:00 2001 From: Ali Masarwa Date: Tue, 6 May 2025 11:17:48 +0300 Subject: [PATCH] RGW/standalone: Build without RadosStore Signed-off-by: Ali Masarwa --- CMakeLists.txt | 1 + src/include/config-h.in.cmake | 3 + src/rgw/CMakeLists.txt | 186 +-- src/rgw/driver/dbstore/config/sqlite.cc | 2 +- src/rgw/driver/rados/rgw_period.cc | 104 -- src/rgw/driver/rados/rgw_rest_realm.cc | 2 +- src/rgw/driver/rados/rgw_user.cc | 62 - src/rgw/driver/rados/rgw_zone.cc | 1334 ----------------- src/rgw/radosgw-admin/radosgw-admin.cc | 14 +- src/rgw/rgw_appmain.cc | 44 +- src/rgw/{driver/rados => }/rgw_bucket_sync.cc | 0 src/rgw/{driver/rados => }/rgw_bucket_sync.h | 1 + src/rgw/rgw_object_expirer.cc | 5 +- src/rgw/rgw_period.cc | 92 ++ src/rgw/rgw_realm_reloader.cc | 3 +- src/rgw/rgw_rest_iam.cc | 2 +- src/rgw/rgw_sal.cc | 18 +- src/rgw/rgw_user.cc | 62 + src/rgw/rgw_zone.cc | 1310 ++++++++++++++++ src/rgw/{driver/rados => }/rgw_zone.h | 3 +- src/rgw/services/svc_mdlog.cc | 2 +- src/rgw/services/svc_zone.cc | 10 - src/rgw/services/svc_zone.h | 4 +- src/test/CMakeLists.txt | 2 +- src/test/rgw/CMakeLists.txt | 12 + src/test/rgw/rgw_cr_test.cc | 2 +- src/test/rgw/test_rgw_iam_policy.cc | 2 +- 27 files changed, 1642 insertions(+), 1640 deletions(-) delete mode 100644 src/rgw/driver/rados/rgw_period.cc delete mode 100644 src/rgw/driver/rados/rgw_zone.cc rename src/rgw/{driver/rados => }/rgw_bucket_sync.cc (100%) rename src/rgw/{driver/rados => }/rgw_bucket_sync.h (99%) rename src/rgw/{driver/rados => }/rgw_zone.h (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 912dfee79d5..5fdd4222245 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -553,6 +553,7 @@ option(WITH_RADOSGW_MOTR "CORTX-Motr backend for RADOS Gateway" OFF) option(WITH_RADOSGW_DAOS "DAOS backend for RADOS Gateway" OFF) option(WITH_RADOSGW_D4N "D4N wrapper for RADOS Gateway" ON) option(WITH_RADOSGW_POSIX "POSIX backend for RADOS Gateway" ON) +option(WITH_RADOSGW_RADOS "RADOS backend for Rados Gateway" ON) option(WITH_RADOSGW_SELECT_PARQUET "Support for s3 select on parquet objects" ON) option(WITH_RADOSGW_ARROW_FLIGHT "Build arrow flight when not using system-provided arrow" OFF) option(WITH_RADOSGW_BACKTRACE_LOGGING "Enable backtraces in rgw logs" OFF) diff --git a/src/include/config-h.in.cmake b/src/include/config-h.in.cmake index bc85aac22ee..25182499cd9 100644 --- a/src/include/config-h.in.cmake +++ b/src/include/config-h.in.cmake @@ -366,6 +366,9 @@ /* Backend POSIX for Rados Gateway */ #cmakedefine WITH_RADOSGW_POSIX +/* Backend RADOS for Rados Gateway */ +#cmakedefine WITH_RADOSGW_RADOS + /* Defined if std::map::merge() is supported */ #cmakedefine HAVE_STDLIB_MAP_SPLICING diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index f235f187936..9fc368f45f2 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -36,26 +36,6 @@ endfunction() find_package(ICU 52.0 COMPONENTS uc REQUIRED) set(librgw_common_srcs - services/svc_finisher.cc - services/svc_bi_rados.cc - services/svc_bilog_rados.cc - services/svc_bucket.cc - services/svc_bucket_sobj.cc - services/svc_bucket_sync_sobj.cc - services/svc_cls.cc - services/svc_config_key_rados.cc - services/svc_mdlog.cc - services/svc_notify.cc - services/svc_quota.cc - services/svc_sync_modules.cc - services/svc_sys_obj.cc - services/svc_sys_obj_cache.cc - services/svc_sys_obj_core.cc - services/svc_tier_rados.cc - services/svc_user.cc - services/svc_user_rados.cc - services/svc_zone.cc - services/svc_zone_utils.cc spdk/crc64.c madler/crc64nvme.c madler/crc32iso_hdlc.c @@ -166,76 +146,97 @@ set(librgw_common_srcs rgw_dedup_cluster.cc rgw_data_access.cc rgw_realm_watcher.cc - driver/rados/account.cc - driver/rados/buckets.cc rgw_bucket_logging.cc rgw_rest_bucket_logging.cc - driver/rados/group.cc - driver/rados/groups.cc - driver/rados/rgw_bucket.cc - driver/rados/rgw_bucket_sync.cc - driver/rados/rgw_cr_rados.cc - driver/rados/rgw_cr_tools.cc - driver/rados/rgw_d3n_datacache.cc - driver/rados/rgw_datalog.cc - driver/rados/rgw_datalog_notify.cc - driver/rados/rgw_data_sync.cc - driver/rados/rgw_etag_verifier.cc - driver/rados/rgw_gc.cc - driver/rados/rgw_gc_log.cc - driver/rados/rgw_lc_tier.cc - driver/rados/rgw_log_backing.cc - driver/rados/rgw_metadata.cc - driver/rados/rgw_notify.cc - driver/rados/rgw_obj_manifest.cc - driver/rados/rgw_object_expirer_core.cc - driver/rados/rgw_otp.cc - driver/rados/rgw_period.cc - driver/rados/rgw_pubsub_push.cc - driver/rados/rgw_putobj_processor.cc - driver/rados/rgw_rados.cc - driver/rados/rgw_reshard.cc - driver/rados/rgw_rest_bucket.cc - driver/rados/rgw_rest_log.cc - driver/rados/rgw_rest_realm.cc - driver/rados/rgw_rest_user.cc - driver/rados/rgw_sal_rados.cc - driver/rados/rgw_service.cc - driver/rados/rgw_sync.cc - driver/rados/rgw_sync_counters.cc - driver/rados/rgw_sync_error_repo.cc - driver/rados/rgw_sync_module.cc - driver/rados/rgw_sync_module_aws.cc - driver/rados/rgw_sync_module_es.cc - driver/rados/rgw_sync_module_es_rest.cc - driver/rados/rgw_sync_module_log.cc - driver/rados/rgw_sync_trace.cc - driver/rados/rgw_tools.cc - driver/rados/rgw_trim_bilog.cc - driver/rados/rgw_trim_datalog.cc - driver/rados/rgw_trim_mdlog.cc - driver/rados/rgw_user.cc - driver/rados/rgw_zone.cc - driver/rados/role.cc - driver/rados/roles.cc - driver/rados/sync_fairness.cc - driver/rados/topic.cc - driver/rados/topic_migration.cc - driver/rados/topics.cc - driver/rados/users.cc) + rgw_bucket_sync.cc) list(APPEND librgw_common_srcs driver/immutable_config/store.cc - driver/json_config/store.cc - driver/rados/config/impl.cc - driver/rados/config/period.cc - driver/rados/config/period_config.cc - driver/rados/config/realm.cc - driver/rados/config/realm_watcher.cc - driver/rados/config/store.cc - driver/rados/config/zone.cc - driver/rados/config/zonegroup.cc) + driver/json_config/store.cc) +if(WITH_RADOSGW_RADOS) + list(APPEND librgw_common_srcs + services/svc_finisher.cc + services/svc_bi_rados.cc + services/svc_bilog_rados.cc + services/svc_bucket.cc + services/svc_bucket_sobj.cc + services/svc_bucket_sync_sobj.cc + services/svc_cls.cc + services/svc_config_key_rados.cc + services/svc_mdlog.cc + services/svc_notify.cc + services/svc_quota.cc + services/svc_sync_modules.cc + services/svc_sys_obj.cc + services/svc_sys_obj_cache.cc + services/svc_sys_obj_core.cc + services/svc_tier_rados.cc + services/svc_user.cc + services/svc_user_rados.cc + services/svc_zone.cc + services/svc_zone_utils.cc + driver/rados/account.cc + driver/rados/buckets.cc + driver/rados/group.cc + driver/rados/groups.cc + driver/rados/rgw_bucket.cc + driver/rados/rgw_cr_rados.cc + driver/rados/rgw_cr_tools.cc + driver/rados/rgw_d3n_datacache.cc + driver/rados/rgw_datalog.cc + driver/rados/rgw_datalog_notify.cc + driver/rados/rgw_data_sync.cc + driver/rados/rgw_etag_verifier.cc + driver/rados/rgw_gc.cc + driver/rados/rgw_gc_log.cc + driver/rados/rgw_lc_tier.cc + driver/rados/rgw_log_backing.cc + driver/rados/rgw_metadata.cc + driver/rados/rgw_notify.cc + driver/rados/rgw_obj_manifest.cc + driver/rados/rgw_object_expirer_core.cc + driver/rados/rgw_otp.cc + driver/rados/rgw_pubsub_push.cc + driver/rados/rgw_putobj_processor.cc + driver/rados/rgw_rados.cc + driver/rados/rgw_reshard.cc + driver/rados/rgw_rest_bucket.cc + driver/rados/rgw_rest_log.cc + driver/rados/rgw_rest_realm.cc + driver/rados/rgw_rest_user.cc + driver/rados/rgw_sal_rados.cc + driver/rados/rgw_service.cc + driver/rados/rgw_sync.cc + driver/rados/rgw_sync_counters.cc + driver/rados/rgw_sync_error_repo.cc + driver/rados/rgw_sync_module.cc + driver/rados/rgw_sync_module_aws.cc + driver/rados/rgw_sync_module_es.cc + driver/rados/rgw_sync_module_es_rest.cc + driver/rados/rgw_sync_module_log.cc + driver/rados/rgw_sync_trace.cc + driver/rados/rgw_tools.cc + driver/rados/rgw_trim_bilog.cc + driver/rados/rgw_trim_datalog.cc + driver/rados/rgw_trim_mdlog.cc + driver/rados/rgw_user.cc + driver/rados/role.cc + driver/rados/roles.cc + driver/rados/sync_fairness.cc + driver/rados/topic.cc + driver/rados/topic_migration.cc + driver/rados/topics.cc + driver/rados/users.cc + driver/rados/config/impl.cc + driver/rados/config/period.cc + driver/rados/config/period_config.cc + driver/rados/config/realm.cc + driver/rados/config/realm_watcher.cc + driver/rados/config/store.cc + driver/rados/config/zone.cc + driver/rados/config/zonegroup.cc) +endif() if(WITH_RADOSGW_AMQP_ENDPOINT) list(APPEND librgw_common_srcs rgw_amqp.cc) endif() @@ -412,10 +413,13 @@ set(rgw_a_srcs rgw_signal.cc rgw_swift_auth.cc rgw_usage.cc - rgw_sts.cc - driver/rados/rgw_rest_bucket.cc - driver/rados/rgw_rest_log.cc - driver/rados/rgw_rest_realm.cc) + rgw_sts.cc) + +if(WITH_RADOSGW_RADOS) + list(APPEND rgw_a_srcs driver/rados/rgw_rest_bucket.cc + driver/rados/rgw_rest_log.cc + driver/rados/rgw_rest_realm.cc) +endif() gperf_generate(${CMAKE_SOURCE_DIR}/src/rgw/rgw_iam_policy_keywords.gperf rgw_iam_policy_keywords.frag.cc) @@ -512,6 +516,7 @@ if(WITH_RADOSGW_ARROW_FLIGHT) list(APPEND radosgw_admin_srcs rgw_flight.cc) endif(WITH_RADOSGW_ARROW_FLIGHT) +if(WITH_RADOSGW_RADOS) add_executable(radosgw-admin ${radosgw_admin_srcs}) target_link_libraries(radosgw-admin legacy-option-headers @@ -522,6 +527,7 @@ target_link_libraries(radosgw-admin global ${LIB_RESOLV} OATH::OATH ${CURL_LIBRARIES} ${EXPAT_LIBRARIES} ${BLKID_LIBRARIES}) +endif() # this is unsatisfying and hopefully temporary; ARROW should not be # part of radosgw_admin @@ -529,7 +535,9 @@ if(WITH_RADOSGW_ARROW_FLIGHT) target_link_libraries(radosgw-admin ${ARROW_LIBRARIES} ${ARROW_FLIGHT_LIBRARIES}) endif(WITH_RADOSGW_ARROW_FLIGHT) +if(WITH_RADOSGW_RADOS) install(TARGETS radosgw-admin DESTINATION bin) +endif() set(radosgw_es_srcs rgw_es_main.cc) @@ -551,6 +559,7 @@ target_link_libraries(radosgw-token global) install(TARGETS radosgw-token DESTINATION bin) +if(WITH_RADOSGW_RADOS) set(radosgw_object_expirer_srcs rgw_object_expirer.cc) add_executable(radosgw-object-expirer ${radosgw_object_expirer_srcs}) @@ -561,6 +570,7 @@ target_link_libraries(radosgw-object-expirer ${rgw_libs} librados global ${LIB_RESOLV} ${CURL_LIBRARIES} ${EXPAT_LIBRARIES}) install(TARGETS radosgw-object-expirer DESTINATION bin) +endif() set(radosgw_polparser_srcs rgw_polparser.cc) diff --git a/src/rgw/driver/dbstore/config/sqlite.cc b/src/rgw/driver/dbstore/config/sqlite.cc index 68ae8f0f239..d80f0cdbf8f 100644 --- a/src/rgw/driver/dbstore/config/sqlite.cc +++ b/src/rgw/driver/dbstore/config/sqlite.cc @@ -27,7 +27,7 @@ #include "common/random_string.h" #include "rgw_realm_watcher.h" -#include "driver/rados/rgw_zone.h" // FIXME: subclass dependency +#include "rgw/rgw_zone.h" #include "common/connection_pool.h" #include "sqlite/connection.h" diff --git a/src/rgw/driver/rados/rgw_period.cc b/src/rgw/driver/rados/rgw_period.cc deleted file mode 100644 index eb57c343918..00000000000 --- a/src/rgw/driver/rados/rgw_period.cc +++ /dev/null @@ -1,104 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab ft=cpp - -#include "rgw_sync.h" -#include "rgw_sal.h" -#include "rgw_sal_config.h" - -#include "services/svc_zone.h" - -#define dout_subsys ceph_subsys_rgw - -using namespace std; -using namespace rgw_zone_defaults; - -int RGWPeriod::get_zonegroup(RGWZoneGroup& zonegroup, - const string& zonegroup_id) const -{ - map::const_iterator iter; - if (!zonegroup_id.empty()) { - iter = period_map.zonegroups.find(zonegroup_id); - } else { - iter = period_map.zonegroups.find("default"); - } - if (iter != period_map.zonegroups.end()) { - zonegroup = iter->second; - return 0; - } - - return -ENOENT; -} - -static int read_sync_status(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver, rgw_meta_sync_status *sync_status) -{ - rgw::sal::RadosStore* rados_store = static_cast(driver); - // initialize a sync status manager to read the status - RGWMetaSyncStatusManager mgr(rados_store, rados_store->svc()->async_processor); - int r = mgr.init(dpp); - if (r < 0) { - return r; - } - r = mgr.read_sync_status(dpp, sync_status); - mgr.stop(); - return r; -} - -int RGWPeriod::update_sync_status(const DoutPrefixProvider *dpp, - rgw::sal::Driver* driver, /* for now */ - const RGWPeriod ¤t_period, - std::ostream& error_stream, - bool force_if_stale) -{ - rgw_meta_sync_status status; - int r = read_sync_status(dpp, driver, &status); - if (r < 0) { - ldpp_dout(dpp, 0) << "period failed to read sync status: " - << cpp_strerror(-r) << dendl; - return r; - } - - std::vector markers; - - const auto current_epoch = current_period.get_realm_epoch(); - if (current_epoch != status.sync_info.realm_epoch) { - // no sync status markers for the current period - ceph_assert(current_epoch > status.sync_info.realm_epoch); - const int behind = current_epoch - status.sync_info.realm_epoch; - if (!force_if_stale && current_epoch > 1) { - error_stream << "ERROR: This zone is " << behind << " period(s) behind " - "the current master zone in metadata sync. If this zone is promoted " - "to master, any metadata changes during that time are likely to " - "be lost.\n" - "Waiting for this zone to catch up on metadata sync (see " - "'radosgw-admin sync status') is recommended.\n" - "To promote this zone to master anyway, add the flag " - "--yes-i-really-mean-it." << std::endl; - return -EINVAL; - } - // empty sync status markers - other zones will skip this period during - // incremental metadata sync - markers.resize(status.sync_info.num_shards); - } else { - markers.reserve(status.sync_info.num_shards); - for (auto& i : status.sync_markers) { - auto& marker = i.second; - // filter out markers from other periods - if (marker.realm_epoch != current_epoch) { - marker.marker.clear(); - } - markers.emplace_back(std::move(marker.marker)); - } - } - - std::swap(sync_status, markers); - return 0; -} - -void RGWPeriod::generate_test_instances(list &o) -{ - RGWPeriod *z = new RGWPeriod; - o.push_back(z); - o.push_back(new RGWPeriod); -} - - diff --git a/src/rgw/driver/rados/rgw_rest_realm.cc b/src/rgw/driver/rados/rgw_rest_realm.cc index 34234a04221..7b941733ae8 100644 --- a/src/rgw/driver/rados/rgw_rest_realm.cc +++ b/src/rgw/driver/rados/rgw_rest_realm.cc @@ -141,7 +141,7 @@ void RGWOp_Period_Post::execute(optional_yield y) // if period id is empty, handle as 'period commit' if (period.get_id().empty()) { - op_ret = rgw::commit_period(this, y, s->penv.cfgstore, driver, realm, *realm_writer, current_period, period, error_stream, false); + op_ret = rgw::commit_period(this, y, s->penv.cfgstore, driver, realm, *realm_writer, current_period, period, error_stream, false, *s->penv.site); if (op_ret == -EEXIST) { op_ret = 0; // succeed on retries so the op is idempotent return; diff --git a/src/rgw/driver/rados/rgw_user.cc b/src/rgw/driver/rados/rgw_user.cc index cce593c6bd5..d90f2de3283 100644 --- a/src/rgw/driver/rados/rgw_user.cc +++ b/src/rgw/driver/rados/rgw_user.cc @@ -32,33 +32,6 @@ static string key_type_to_str(int key_type) { } } -static bool char_is_unreserved_url(char c) -{ - if (isalnum(c)) - return true; - - switch (c) { - case '-': - case '.': - case '_': - case '~': - return true; - default: - return false; - } -} - -static bool validate_access_key(string& key) -{ - const char *p = key.c_str(); - while (*p) { - if (!char_is_unreserved_url(*p)) - return false; - p++; - } - return true; -} - static void set_err_msg(std::string *sink, std::string msg) { if (sink && !msg.empty()) @@ -502,41 +475,6 @@ int RGWAccessKeyPool::check_op(RGWUserAdminOpState& op_state, return 0; } -void rgw_generate_secret_key(CephContext* cct, - std::string& secret_key) -{ - char secret_key_buf[SECRET_KEY_LEN + 1]; - gen_rand_alphanumeric_plain(cct, secret_key_buf, sizeof(secret_key_buf)); - secret_key = secret_key_buf; -} - -int rgw_generate_access_key(const DoutPrefixProvider* dpp, - optional_yield y, - rgw::sal::Driver* driver, - std::string& access_key_id) -{ - std::string id; - int r = 0; - - do { - id.resize(PUBLIC_ID_LEN + 1); - gen_rand_alphanumeric_upper(dpp->get_cct(), id.data(), id.size()); - id.pop_back(); // remove trailing null - - if (!validate_access_key(id)) - continue; - - std::unique_ptr duplicate_check; - r = driver->get_user_by_access_key(dpp, id, y, &duplicate_check); - } while (r == 0); - - if (r == -ENOENT) { - access_key_id = std::move(id); - return 0; - } - return r; -} - // Generate a new random key int RGWAccessKeyPool::generate_key(const DoutPrefixProvider *dpp, RGWUserAdminOpState& op_state, optional_yield y, std::string *err_msg) diff --git a/src/rgw/driver/rados/rgw_zone.cc b/src/rgw/driver/rados/rgw_zone.cc deleted file mode 100644 index 804a47ad03d..00000000000 --- a/src/rgw/driver/rados/rgw_zone.cc +++ /dev/null @@ -1,1334 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab ft=cpp - -#include "rgw_zone.h" -#include "rgw_realm_watcher.h" -#include "rgw_sal_config.h" -#include "rgw_sync.h" - -#include "services/svc_zone.h" - -#define dout_context g_ceph_context -#define dout_subsys ceph_subsys_rgw - -using namespace std; -using namespace rgw_zone_defaults; - -RGWMetaSyncStatusManager::~RGWMetaSyncStatusManager(){} - -#define FIRST_EPOCH 1 - -struct RGWAccessKey; - -namespace rgw { -/// Generate a random uuid for realm/period/zonegroup/zone ids -std::string gen_random_uuid() -{ - uuid_d uuid; - uuid.generate_random(); - return uuid.to_string(); -} -} - -void RGWDefaultZoneGroupInfo::dump(Formatter *f) const { - encode_json("default_zonegroup", default_zonegroup, f); -} - -void RGWDefaultZoneGroupInfo::decode_json(JSONObj *obj) { - - JSONDecoder::decode_json("default_zonegroup", default_zonegroup, obj); - /* backward compatability with region */ - if (default_zonegroup.empty()) { - JSONDecoder::decode_json("default_region", default_zonegroup, obj); - } -} - -int RGWZoneGroup::equals(const string& other_zonegroup) const -{ - if (is_master && other_zonegroup.empty()) - return true; - - return (id == other_zonegroup); -} - -void RGWDefaultSystemMetaObjInfo::dump(Formatter *f) const { - encode_json("default_id", default_id, f); -} - -void RGWDefaultSystemMetaObjInfo::decode_json(JSONObj *obj) { - JSONDecoder::decode_json("default_id", default_id, obj); -} - -const string& RGWZoneParams::get_compression_type(const rgw_placement_rule& placement_rule) const -{ - static const std::string NONE{"none"}; - auto p = placement_pools.find(placement_rule.name); - if (p == placement_pools.end()) { - return NONE; - } - const auto& type = p->second.get_compression_type(placement_rule.get_storage_class()); - return !type.empty() ? type : NONE; -} - -// run an MD5 hash on the zone_id and return the first 32 bits -static uint32_t gen_short_zone_id(const std::string zone_id) -{ - unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE]; - MD5 hash; - // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes - hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - hash.Update((const unsigned char *)zone_id.c_str(), zone_id.size()); - hash.Final(md5); - - uint32_t short_id; - memcpy((char *)&short_id, md5, sizeof(short_id)); - return std::max(short_id, 1u); -} - -int RGWPeriodMap::update(const RGWZoneGroup& zonegroup, CephContext *cct) -{ - if (zonegroup.is_master_zonegroup() && (!master_zonegroup.empty() && zonegroup.get_id() != master_zonegroup)) { - ldout(cct,0) << "Error updating periodmap, multiple master zonegroups configured "<< dendl; - ldout(cct,0) << "master zonegroup: " << master_zonegroup << " and " << zonegroup.get_id() <::iterator iter = zonegroups.find(zonegroup.get_id()); - if (iter != zonegroups.end()) { - RGWZoneGroup& old_zonegroup = iter->second; - if (!old_zonegroup.api_name.empty()) { - zonegroups_by_api.erase(old_zonegroup.api_name); - } - } - zonegroups[zonegroup.get_id()] = zonegroup; - - if (!zonegroup.api_name.empty()) { - zonegroups_by_api[zonegroup.api_name] = zonegroup; - } - - if (zonegroup.is_master_zonegroup()) { - master_zonegroup = zonegroup.get_id(); - } else if (master_zonegroup == zonegroup.get_id()) { - master_zonegroup = ""; - } - - for (auto& i : zonegroup.zones) { - auto& zone = i.second; - if (short_zone_ids.find(zone.id) != short_zone_ids.end()) { - continue; - } - // calculate the zone's short id - uint32_t short_id = gen_short_zone_id(zone.id); - - // search for an existing zone with the same short id - for (auto& s : short_zone_ids) { - if (s.second == short_id) { - ldout(cct, 0) << "New zone '" << zone.name << "' (" << zone.id - << ") generates the same short_zone_id " << short_id - << " as existing zone id " << s.first << dendl; - return -EEXIST; - } - } - - short_zone_ids[zone.id] = short_id; - } - - return 0; -} - -uint32_t RGWPeriodMap::get_zone_short_id(const string& zone_id) const -{ - auto i = short_zone_ids.find(zone_id); - if (i == short_zone_ids.end()) { - return 0; - } - return i->second; -} - -bool RGWPeriodMap::find_zone_by_name(const string& zone_name, - RGWZoneGroup *zonegroup, - RGWZone *zone) const -{ - for (auto& iter : zonegroups) { - auto& zg = iter.second; - for (auto& ziter : zg.zones) { - auto& z = ziter.second; - - if (z.name == zone_name) { - *zonegroup = zg; - *zone = z; - return true; - } - } - } - - return false; -} - -namespace rgw { - -int read_realm(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, - std::string_view realm_id, - std::string_view realm_name, - RGWRealm& info, - std::unique_ptr* writer) -{ - if (!realm_id.empty()) { - return cfgstore->read_realm_by_id(dpp, y, realm_id, info, writer); - } - if (!realm_name.empty()) { - return cfgstore->read_realm_by_name(dpp, y, realm_name, info, writer); - } - return cfgstore->read_default_realm(dpp, y, info, writer); -} - -int create_realm(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, bool exclusive, - RGWRealm& info, - std::unique_ptr* writer_out) -{ - if (info.name.empty()) { - ldpp_dout(dpp, -1) << __func__ << " requires a realm name" << dendl; - return -EINVAL; - } - if (info.id.empty()) { - info.id = gen_random_uuid(); - } - - // if the realm already has a current_period, just make sure it exists - std::optional period; - if (!info.current_period.empty()) { - period.emplace(); - int r = cfgstore->read_period(dpp, y, info.current_period, - std::nullopt, *period); - if (r < 0) { - ldpp_dout(dpp, -1) << __func__ << " failed to read realm's current_period=" - << info.current_period << " with " << cpp_strerror(r) << dendl; - return r; - } - } - - // create the realm - std::unique_ptr writer; - int r = cfgstore->create_realm(dpp, y, exclusive, info, &writer); - if (r < 0) { - return r; - } - - if (!period) { - // initialize and exclusive-create the initial period - period.emplace(); - period->id = gen_random_uuid(); - period->period_map.id = period->id; - period->epoch = FIRST_EPOCH; - period->realm_id = info.id; - - r = cfgstore->create_period(dpp, y, true, *period); - if (r < 0) { - ldpp_dout(dpp, -1) << __func__ << " failed to create the initial period id=" - << period->id << " for realm " << info.name - << " with " << cpp_strerror(r) << dendl; - return r; - } - } - - // update the realm's current_period - r = realm_set_current_period(dpp, y, cfgstore, *writer, info, *period); - if (r < 0) { - return r; - } - - if (writer_out) { - *writer_out = std::move(writer); - } - return 0; -} - -int set_default_realm(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, const RGWRealm& info, - bool exclusive) -{ - return cfgstore->write_default_realm_id(dpp, y, exclusive, info.id); -} - -int realm_set_current_period(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, - sal::RealmWriter& writer, RGWRealm& realm, - const RGWPeriod& period) -{ - // update realm epoch to match the period's - if (realm.epoch > period.realm_epoch) { - ldpp_dout(dpp, -1) << __func__ << " with old realm epoch " - << period.realm_epoch << ", current epoch=" << realm.epoch << dendl; - return -EINVAL; - } - if (realm.epoch == period.realm_epoch && realm.current_period != period.id) { - ldpp_dout(dpp, -1) << __func__ << " with same realm epoch " - << period.realm_epoch << ", but different period id " - << period.id << " != " << realm.current_period << dendl; - return -EINVAL; - } - - realm.epoch = period.realm_epoch; - realm.current_period = period.id; - - // update the realm object - int r = writer.write(dpp, y, realm); - if (r < 0) { - ldpp_dout(dpp, -1) << __func__ << " failed to overwrite realm " - << realm.name << " with " << cpp_strerror(r) << dendl; - return r; - } - - // reflect the zonegroup and period config - (void) reflect_period(dpp, y, cfgstore, period); - return 0; -} - -int reflect_period(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, const RGWPeriod& info) -{ - // overwrite the local period config and zonegroup objects - constexpr bool exclusive = false; - - int r = cfgstore->write_period_config(dpp, y, exclusive, info.realm_id, - info.period_config); - if (r < 0) { - ldpp_dout(dpp, -1) << __func__ << " failed to store period config for realm id=" - << info.realm_id << " with " << cpp_strerror(r) << dendl; - return r; - } - - for (auto& [zonegroup_id, zonegroup] : info.period_map.zonegroups) { - r = cfgstore->create_zonegroup(dpp, y, exclusive, zonegroup, nullptr); - if (r < 0) { - ldpp_dout(dpp, -1) << __func__ << " failed to store zonegroup id=" - << zonegroup_id << " with " << cpp_strerror(r) << dendl; - return r; - } - if (zonegroup.is_master) { - // set master as default if no default exists - constexpr bool exclusive = true; - r = set_default_zonegroup(dpp, y, cfgstore, zonegroup, exclusive); - if (r == 0) { - ldpp_dout(dpp, 1) << "Set the period's master zonegroup " - << zonegroup.name << " as the default" << dendl; - } - } - } - return 0; -} - -std::string get_staging_period_id(std::string_view realm_id) -{ - return string_cat_reserve(realm_id, ":staging"); -} - -void fork_period(const DoutPrefixProvider* dpp, RGWPeriod& info) -{ - ldpp_dout(dpp, 20) << __func__ << " realm id=" << info.realm_id - << " period id=" << info.id << dendl; - - info.predecessor_uuid = std::move(info.id); - info.id = get_staging_period_id(info.realm_id); - info.period_map.reset(); - info.realm_epoch++; -} - -int update_period(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, RGWPeriod& info) -{ - // clear zone short ids of removed zones. period_map.update() will add the - // remaining zones back - info.period_map.short_zone_ids.clear(); - - // list all zonegroups in the realm - rgw::sal::ListResult listing; - std::array zonegroup_names; // list in pages of 1000 - do { - int ret = cfgstore->list_zonegroup_names(dpp, y, listing.next, - zonegroup_names, listing); - if (ret < 0) { - std::cerr << "failed to list zonegroups: " << cpp_strerror(-ret) << std::endl; - return -ret; - } - for (const auto& name : listing.entries) { - RGWZoneGroup zg; - ret = cfgstore->read_zonegroup_by_name(dpp, y, name, zg, nullptr); - if (ret < 0) { - ldpp_dout(dpp, 0) << "WARNING: failed to read zonegroup " - << name << ": " << cpp_strerror(-ret) << dendl; - continue; - } - - if (zg.realm_id != info.realm_id) { - ldpp_dout(dpp, 20) << "skipping zonegroup " << zg.get_name() - << " with realm id " << zg.realm_id - << ", not on our realm " << info.realm_id << dendl; - continue; - } - - if (zg.master_zone.empty()) { - ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name() << " should have a master zone " << dendl; - return -EINVAL; - } - - if (zg.zones.find(zg.master_zone) == zg.zones.end()) { - ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name() - << " has a non existent master zone "<< dendl; - return -EINVAL; - } - - if (zg.is_master_zonegroup()) { - info.master_zonegroup = zg.get_id(); - info.master_zone = zg.master_zone; - } - - ret = info.period_map.update(zg, dpp->get_cct()); - if (ret < 0) { - return ret; - } - } // foreach name in listing.entries - } while (!listing.next.empty()); - - // read the realm's current period config - int ret = cfgstore->read_period_config(dpp, y, info.realm_id, - info.period_config); - if (ret < 0 && ret != -ENOENT) { - ldpp_dout(dpp, 0) << "ERROR: failed to read period config: " - << cpp_strerror(ret) << dendl; - return ret; - } - - return 0; -} - -int commit_period(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, sal::Driver* driver, - RGWRealm& realm, sal::RealmWriter& realm_writer, - const RGWPeriod& current_period, - RGWPeriod& info, std::ostream& error_stream, - bool force_if_stale) -{ - ldpp_dout(dpp, 20) << __func__ << " realm " << realm.id - << " period " << current_period.id << dendl; - auto zone_svc = static_cast(driver)->svc()->zone; // XXX - - // gateway must be in the master zone to commit - if (info.master_zone != zone_svc->get_zone_params().id) { - error_stream << "Cannot commit period on zone " - << zone_svc->get_zone_params().id << ", it must be sent to " - "the period's master zone " << info.master_zone << '.' << std::endl; - return -EINVAL; - } - // period predecessor must match current period - if (info.predecessor_uuid != current_period.id) { - error_stream << "Period predecessor " << info.predecessor_uuid - << " does not match current period " << current_period.id - << ". Use 'period pull' to get the latest period from the master, " - "reapply your changes, and try again." << std::endl; - return -EINVAL; - } - // realm epoch must be 1 greater than current period - if (info.realm_epoch != current_period.realm_epoch + 1) { - error_stream << "Period's realm epoch " << info.realm_epoch - << " does not come directly after current realm epoch " - << current_period.realm_epoch << ". Use 'realm pull' to get the " - "latest realm and period from the master zone, reapply your changes, " - "and try again." << std::endl; - return -EINVAL; - } - // did the master zone change? - if (info.master_zone != current_period.master_zone) { - // store the current metadata sync status in the period - int r = info.update_sync_status(dpp, driver, current_period, - error_stream, force_if_stale); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to update metadata sync status: " - << cpp_strerror(-r) << dendl; - return r; - } - // create an object with a new period id - info.period_map.id = info.id = gen_random_uuid(); - info.epoch = FIRST_EPOCH; - - constexpr bool exclusive = true; - r = cfgstore->create_period(dpp, y, exclusive, info); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to create new period: " << cpp_strerror(-r) << dendl; - return r; - } - // set as current period - r = realm_set_current_period(dpp, y, cfgstore, realm_writer, realm, info); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to update realm's current period: " - << cpp_strerror(-r) << dendl; - return r; - } - ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period " - << info.id << dendl; - return 0; - } - // period must be based on current epoch - if (info.epoch != current_period.epoch) { - error_stream << "Period epoch " << info.epoch << " does not match " - "predecessor epoch " << current_period.epoch << ". Use " - "'period pull' to get the latest epoch from the master zone, " - "reapply your changes, and try again." << std::endl; - return -EINVAL; - } - // set period as next epoch - info.id = current_period.id; - info.epoch = current_period.epoch + 1; - info.predecessor_uuid = current_period.predecessor_uuid; - info.realm_epoch = current_period.realm_epoch; - // write the period - constexpr bool exclusive = true; - int r = cfgstore->create_period(dpp, y, exclusive, info); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to store period: " << cpp_strerror(r) << dendl; - return r; - } - r = reflect_period(dpp, y, cfgstore, info); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to update local objects: " << cpp_strerror(r) << dendl; - return r; - } - ldpp_dout(dpp, 4) << "Committed new epoch " << info.epoch - << " for period " << info.id << dendl; - return 0; -} - - -int read_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, - std::string_view zonegroup_id, - std::string_view zonegroup_name, - RGWZoneGroup& info, - std::unique_ptr* writer) -{ - if (!zonegroup_id.empty()) { - return cfgstore->read_zonegroup_by_id(dpp, y, zonegroup_id, info, writer); - } - if (!zonegroup_name.empty()) { - return cfgstore->read_zonegroup_by_name(dpp, y, zonegroup_name, info, writer); - } - - std::string realm_id; - int r = cfgstore->read_default_realm_id(dpp, y, realm_id); - if (r == -ENOENT) { - return cfgstore->read_zonegroup_by_name(dpp, y, default_zonegroup_name, - info, writer); - } - if (r < 0) { - return r; - } - return cfgstore->read_default_zonegroup(dpp, y, realm_id, info, writer); -} - -int create_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, bool exclusive, - RGWZoneGroup& info) -{ - if (info.name.empty()) { - ldpp_dout(dpp, -1) << __func__ << " requires a zonegroup name" << dendl; - return -EINVAL; - } - if (info.id.empty()) { - info.id = gen_random_uuid(); - } - - // insert the default placement target if it doesn't exist - constexpr std::string_view default_placement_name = "default-placement"; - - RGWZoneGroupPlacementTarget placement_target; - placement_target.name = default_placement_name; - - info.placement_targets.emplace(default_placement_name, placement_target); - if (info.default_placement.name.empty()) { - info.default_placement.name = default_placement_name; - } - - int r = cfgstore->create_zonegroup(dpp, y, exclusive, info, nullptr); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to create zonegroup with " - << cpp_strerror(r) << dendl; - return r; - } - - // try to set as default. may race with another create, so pass exclusive=true - // so we don't override an existing default - r = set_default_zonegroup(dpp, y, cfgstore, info, true); - if (r < 0 && r != -EEXIST) { - ldpp_dout(dpp, 0) << "WARNING: failed to set zonegroup as default: " - << cpp_strerror(r) << dendl; - } - - return 0; -} - -static int create_default_zonegroup(const DoutPrefixProvider* dpp, - optional_yield y, - sal::ConfigStore* cfgstore, - bool exclusive, - const RGWZoneParams& default_zone, - RGWZoneGroup& info) -{ - info.name = default_zonegroup_name; - info.api_name = default_zonegroup_name; - info.is_master = true; - - // enable all supported features - info.enabled_features.insert(rgw::zone_features::enabled.begin(), - rgw::zone_features::enabled.end()); - - // add the zone to the zonegroup - bool is_master = true; - std::list empty_list; - rgw::zone_features::set disable_features; // empty - int r = add_zone_to_group(dpp, info, default_zone, &is_master, nullptr, - empty_list, nullptr, nullptr, empty_list, - empty_list, nullptr, std::nullopt, - info.enabled_features, disable_features); - if (r < 0) { - return r; - } - - // write the zone - return create_zonegroup(dpp, y, cfgstore, exclusive, info); -} - -int set_default_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, const RGWZoneGroup& info, - bool exclusive) -{ - return cfgstore->write_default_zonegroup_id( - dpp, y, exclusive, info.realm_id, info.id); -} - -int remove_zone_from_group(const DoutPrefixProvider* dpp, - RGWZoneGroup& zonegroup, - const rgw_zone_id& zone_id) -{ - auto z = zonegroup.zones.find(zone_id); - if (z == zonegroup.zones.end()) { - return -ENOENT; - } - zonegroup.zones.erase(z); - - if (zonegroup.master_zone == zone_id) { - // choose a new master zone - auto m = zonegroup.zones.begin(); - if (m != zonegroup.zones.end()) { - zonegroup.master_zone = m->first; - ldpp_dout(dpp, 0) << "NOTICE: promoted " << m->second.name - << " as new master_zone of zonegroup " << zonegroup.name << dendl; - } else { - ldpp_dout(dpp, 0) << "NOTICE: removed master_zone of zonegroup " - << zonegroup.name << dendl; - } - } - - const bool log_data = zonegroup.zones.size() > 1; - for (auto& [id, zone] : zonegroup.zones) { - zone.log_data = log_data; - } - - return 0; -} - -// try to remove the given zone id from every zonegroup in the cluster -static int remove_zone_from_groups(const DoutPrefixProvider* dpp, - optional_yield y, - sal::ConfigStore* cfgstore, - const rgw_zone_id& zone_id) -{ - std::array zonegroup_names; - sal::ListResult listing; - do { - int r = cfgstore->list_zonegroup_names(dpp, y, listing.next, - zonegroup_names, listing); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to list zonegroups with " - << cpp_strerror(r) << dendl; - return r; - } - - for (const auto& name : listing.entries) { - RGWZoneGroup zonegroup; - std::unique_ptr writer; - r = cfgstore->read_zonegroup_by_name(dpp, y, name, zonegroup, &writer); - if (r < 0) { - ldpp_dout(dpp, 0) << "WARNING: failed to load zonegroup " << name - << " with " << cpp_strerror(r) << dendl; - continue; - } - - r = remove_zone_from_group(dpp, zonegroup, zone_id); - if (r < 0) { - continue; - } - - // write the updated zonegroup - r = writer->write(dpp, y, zonegroup); - if (r < 0) { - ldpp_dout(dpp, 0) << "WARNING: failed to write zonegroup " << name - << " with " << cpp_strerror(r) << dendl; - continue; - } - ldpp_dout(dpp, 0) << "Removed zone from zonegroup " << name << dendl; - } - } while (!listing.next.empty()); - - return 0; -} - - -int read_zone(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, - std::string_view zone_id, - std::string_view zone_name, - RGWZoneParams& info, - std::unique_ptr* writer) -{ - if (!zone_id.empty()) { - return cfgstore->read_zone_by_id(dpp, y, zone_id, info, writer); - } - if (!zone_name.empty()) { - return cfgstore->read_zone_by_name(dpp, y, zone_name, info, writer); - } - - std::string realm_id; - int r = cfgstore->read_default_realm_id(dpp, y, realm_id); - if (r == -ENOENT) { - return cfgstore->read_zone_by_name(dpp, y, default_zone_name, info, writer); - } - if (r < 0) { - return r; - } - return cfgstore->read_default_zone(dpp, y, realm_id, info, writer); -} - -extern int get_zones_pool_set(const DoutPrefixProvider *dpp, optional_yield y, - rgw::sal::ConfigStore* cfgstore, - std::string_view my_zone_id, - std::set& pools); - -int create_zone(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, bool exclusive, - RGWZoneParams& info, std::unique_ptr* writer) -{ - if (info.name.empty()) { - ldpp_dout(dpp, -1) << __func__ << " requires a zone name" << dendl; - return -EINVAL; - } - if (info.id.empty()) { - info.id = gen_random_uuid(); - } - - // add default placement with empty pool name - RGWZonePlacementInfo placement; - rgw_pool pool; - placement.storage_classes.set_storage_class( - RGW_STORAGE_CLASS_STANDARD, &pool, nullptr); - // don't overwrite if it already exists - info.placement_pools.emplace("default-placement", std::move(placement)); - - // build a set of all pool names used by other zones - std::set pools; - int r = get_zones_pool_set(dpp, y, cfgstore, info.id, pools); - if (r < 0) { - return r; - } - - // initialize pool names with the zone name prefix - r = init_zone_pool_names(dpp, y, pools, info); - if (r < 0) { - return r; - } - - r = cfgstore->create_zone(dpp, y, exclusive, info, nullptr); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to create zone with " - << cpp_strerror(r) << dendl; - return r; - } - - // try to set as default. may race with another create, so pass exclusive=true - // so we don't override an existing default - r = set_default_zone(dpp, y, cfgstore, info, true); - if (r < 0 && r != -EEXIST) { - ldpp_dout(dpp, 0) << "WARNING: failed to set zone as default: " - << cpp_strerror(r) << dendl; - } - - return 0; - -} - -int set_default_zone(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, const RGWZoneParams& info, - bool exclusive) -{ - return cfgstore->write_default_zone_id( - dpp, y, exclusive, info.realm_id, info.id); -} - -int delete_zone(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, const RGWZoneParams& info, - sal::ZoneWriter& writer) -{ - // remove this zone from any zonegroups that contain it - int r = remove_zone_from_groups(dpp, y, cfgstore, info.id); - if (r < 0) { - return r; - } - - return writer.remove(dpp, y); -} - -auto find_zone_placement(const DoutPrefixProvider* dpp, - const RGWZoneParams& info, - const rgw_placement_rule& rule) - -> const RGWZonePlacementInfo* -{ - auto i = info.placement_pools.find(rule.name); - if (i == info.placement_pools.end()) { - ldpp_dout(dpp, 0) << "ERROR: This zone does not contain placement rule " - << rule.name << dendl; - return nullptr; - } - - const std::string& storage_class = rule.get_storage_class(); - if (!i->second.storage_class_exists(storage_class)) { - ldpp_dout(dpp, 5) << "ERROR: The zone placement for rule " << rule.name - << " does not contain storage class " << storage_class << dendl; - return nullptr; - } - - return &i->second; -} - -bool all_zonegroups_support(const SiteConfig& site, std::string_view feature) -{ - const auto& period = site.get_period(); - if (!period) { - // if we're not in a realm, just check the local zonegroup - return site.get_zonegroup().supports(feature); - } - const auto& zgs = period->period_map.zonegroups; - return std::all_of(zgs.begin(), zgs.end(), [feature] (const auto& pair) { - return pair.second.supports(feature); - }); -} - -static int read_or_create_default_zone(const DoutPrefixProvider* dpp, - optional_yield y, - sal::ConfigStore* cfgstore, - RGWZoneParams& info) -{ - int r = cfgstore->read_zone_by_name(dpp, y, default_zone_name, info, nullptr); - if (r == -ENOENT) { - info.name = default_zone_name; - constexpr bool exclusive = true; - r = create_zone(dpp, y, cfgstore, exclusive, info, nullptr); - if (r == -EEXIST) { - r = cfgstore->read_zone_by_name(dpp, y, default_zone_name, info, nullptr); - } - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to create default zone: " - << cpp_strerror(r) << dendl; - return r; - } - } - return r; -} - -static int read_or_create_default_zonegroup(const DoutPrefixProvider* dpp, - optional_yield y, - sal::ConfigStore* cfgstore, - const RGWZoneParams& zone_params, - RGWZoneGroup& info) -{ - int r = cfgstore->read_zonegroup_by_name(dpp, y, default_zonegroup_name, - info, nullptr); - if (r == -ENOENT) { - constexpr bool exclusive = true; - r = create_default_zonegroup(dpp, y, cfgstore, exclusive, - zone_params, info); - if (r == -EEXIST) { - r = cfgstore->read_zonegroup_by_name(dpp, y, default_zonegroup_name, - info, nullptr); - } - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to create default zonegroup: " - << cpp_strerror(r) << dendl; - return r; - } - } - return r; -} - -int SiteConfig::load(const DoutPrefixProvider* dpp, optional_yield y, - sal::ConfigStore* cfgstore, bool force_local_zonegroup) -{ - // clear existing configuration - zone = nullptr; - zonegroup = nullptr; - local_zonegroup = std::nullopt; - period = std::nullopt; - zone_params = RGWZoneParams{}; - - int r = 0; - - // try to load a realm - realm.emplace(); - std::string realm_name = dpp->get_cct()->_conf->rgw_realm; - if (!realm_name.empty()) { - r = cfgstore->read_realm_by_name(dpp, y, realm_name, *realm, nullptr); - } else { - r = cfgstore->read_default_realm(dpp, y, *realm, nullptr); - if (r == -ENOENT) { // no realm - r = 0; - realm = std::nullopt; - } - } - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to load realm: " << cpp_strerror(r) << dendl; - return r; - } - - // try to load the local zone params - std::string zone_name = dpp->get_cct()->_conf->rgw_zone; - if (!zone_name.empty()) { - r = cfgstore->read_zone_by_name(dpp, y, zone_name, zone_params, nullptr); - } else if (realm) { - // load the realm's default zone - r = cfgstore->read_default_zone(dpp, y, realm->id, zone_params, nullptr); - if (r == -ENOENT) { - if (realm_name.empty()) { - // rgw_realm was not specified, and we found a default realm that - // doesn't have a default zone. ignore the realm and try to load the - // global default zone - realm = std::nullopt; - r = read_or_create_default_zone(dpp, y, cfgstore, zone_params); - } else { - ldpp_dout(dpp, 0) << "No rgw_zone configured, and the selected realm \"" - << realm->name << "\" does not have a default zone." << dendl; - } - } - } else { - // load or create the "default" zone - r = read_or_create_default_zone(dpp, y, cfgstore, zone_params); - } - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to load zone: " << cpp_strerror(r) << dendl; - return r; - } - - if (!realm && !zone_params.realm_id.empty()) { - realm.emplace(); - r = cfgstore->read_realm_by_id(dpp, y, zone_params.realm_id, - *realm, nullptr); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to load realm: " << cpp_strerror(r) << dendl; - return r; - } - } - - if (realm && !force_local_zonegroup) { - // try to load the realm's period - r = load_period_zonegroup(dpp, y, cfgstore, *realm, zone_params.id); - if (r != -ENOENT) { - return r; - } - ldpp_dout(dpp, 10) << "cannot find current period zonegroup, " - "using local zonegroup configuration" << dendl; - } - - // fall back to a local zonegroup - return load_local_zonegroup(dpp, y, cfgstore, zone_params.id); -} - -std::unique_ptr SiteConfig::make_fake() { - auto fake = std::make_unique(); - fake->local_zonegroup.emplace(); - fake->local_zonegroup->zones.emplace(""s, RGWZone{}); - fake->zonegroup = &*fake->local_zonegroup; - fake->zone = &fake->zonegroup->zones.begin()->second; - return fake; -} - -int SiteConfig::load_period_zonegroup(const DoutPrefixProvider* dpp, - optional_yield y, - sal::ConfigStore* cfgstore, - const RGWRealm& realm, - const rgw_zone_id& zone_id) -{ - // load the realm's current period - period.emplace(); - int r = cfgstore->read_period(dpp, y, realm.current_period, - std::nullopt, *period); - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to load current period: " - << cpp_strerror(r) << dendl; - return r; - } - - // find our zone and zonegroup in the period - for (const auto& zg : period->period_map.zonegroups) { - auto z = zg.second.zones.find(zone_id); - if (z != zg.second.zones.end()) { - zone = &z->second; - zonegroup = &zg.second; - return 0; - } - } - - ldpp_dout(dpp, 0) << "ERROR: current period " << period->id - << " does not contain zone id " << zone_id << dendl; - - period = std::nullopt; - return -ENOENT; -} - -int SiteConfig::load_local_zonegroup(const DoutPrefixProvider* dpp, - optional_yield y, - sal::ConfigStore* cfgstore, - const rgw_zone_id& zone_id) -{ - int r = 0; - - // load the zonegroup - local_zonegroup.emplace(); - std::string zonegroup_name = dpp->get_cct()->_conf->rgw_zonegroup; - if (!zonegroup_name.empty()) { - r = cfgstore->read_zonegroup_by_name(dpp, y, zonegroup_name, - *local_zonegroup, nullptr); - } else if (realm) { - r = cfgstore->read_default_zonegroup(dpp, y, realm->id, - *local_zonegroup, nullptr); - } else { - r = read_or_create_default_zonegroup(dpp, y, cfgstore, zone_params, - *local_zonegroup); - } - - if (r < 0) { - ldpp_dout(dpp, 0) << "failed to load zonegroup: " - << cpp_strerror(r) << dendl; - } else { - // find our zone in the zonegroup - auto z = local_zonegroup->zones.find(zone_id); - if (z != local_zonegroup->zones.end()) { - zone = &z->second; - zonegroup = &*local_zonegroup; - return 0; - } - ldpp_dout(dpp, 0) << "ERROR: zonegroup " << local_zonegroup->id - << " does not contain zone id " << zone_id << dendl; - r = -ENOENT; - } - - local_zonegroup = std::nullopt; - return r; -} - -} // namespace rgw - -static inline int conf_to_uint64(const JSONFormattable& config, const string& key, uint64_t *pval) -{ - string sval; - if (config.find(key, &sval)) { - string err; - uint64_t val = strict_strtoll(sval.c_str(), 10, &err); - if (!err.empty()) { - return -EINVAL; - } - *pval = val; - } - return 0; -} - -int RGWZoneGroupPlacementTier::update_params(const JSONFormattable& config) -{ - int r = -1; - - if (config.exists("retain_head_object")) { - string s = config["retain_head_object"]; - if (s == "true") { - retain_head_object = true; - } else { - retain_head_object = false; - } - } - if (config.exists("allow_read_through")) { - string s = config["allow_read_through"]; - if (s == "true") { - allow_read_through = true; - } else { - allow_read_through = false; - } - } - if (config.exists("read_through_restore_days")) { - r = conf_to_uint64(config, "read_through_restore_days", &read_through_restore_days); - if (r < 0) { - read_through_restore_days = DEFAULT_READ_THROUGH_RESTORE_DAYS; - } - } - - if (is_tier_type_s3()) { - r = t.s3.update_params(config); - } - - if (config.exists("restore_storage_class")) { - restore_storage_class = config["restore_storage_class"]; - } - - if (is_tier_type_s3_glacier()) { - r = s3_glacier.update_params(config); - } - return r; -} - -int RGWZoneGroupPlacementTier::clear_params(const JSONFormattable& config) -{ - if (config.exists("retain_head_object")) { - retain_head_object = false; - } - if (config.exists("allow_read_through")) { - allow_read_through = false; - } - if (config.exists("read_through_restore_days")) { - read_through_restore_days = DEFAULT_READ_THROUGH_RESTORE_DAYS; - } - - if (is_tier_type_s3()) { - t.s3.clear_params(config); - } - - if (config.exists("restore_storage_class")) { - restore_storage_class = RGW_STORAGE_CLASS_STANDARD; - } - - if (is_tier_type_s3_glacier()) { - s3_glacier.clear_params(config); - } - - return 0; -} - -int RGWZoneGroupPlacementTierS3::update_params(const JSONFormattable& config) -{ - int r = -1; - - if (config.exists("endpoint")) { - endpoint = config["endpoint"]; - } - if (config.exists("target_path")) { - target_path = config["target_path"]; - } - if (config.exists("region")) { - region = config["region"]; - } - if (config.exists("host_style")) { - string s; - s = config["host_style"]; - if (s != "virtual") { - host_style = PathStyle; - } else { - host_style = VirtualStyle; - } - } - if (config.exists("target_storage_class")) { - target_storage_class = config["target_storage_class"]; - } - if (config.exists("access_key")) { - key.id = config["access_key"]; - } - if (config.exists("secret")) { - key.key = config["secret"]; - } - if (config.exists("multipart_sync_threshold")) { - r = conf_to_uint64(config, "multipart_sync_threshold", &multipart_sync_threshold); - if (r < 0) { - multipart_sync_threshold = DEFAULT_MULTIPART_SYNC_PART_SIZE; - } - } - - if (config.exists("multipart_min_part_size")) { - r = conf_to_uint64(config, "multipart_min_part_size", &multipart_min_part_size); - if (r < 0) { - multipart_min_part_size = DEFAULT_MULTIPART_SYNC_PART_SIZE; - } - } - - if (config.exists("acls")) { - const JSONFormattable& cc = config["acls"]; - if (cc.is_array()) { - for (auto& c : cc.array()) { - RGWTierACLMapping m; - m.init(c); - if (!m.source_id.empty()) { - acl_mappings[m.source_id] = m; - } - } - } else { - RGWTierACLMapping m; - m.init(cc); - if (!m.source_id.empty()) { - acl_mappings[m.source_id] = m; - } - } - } - return 0; -} - -int RGWZoneGroupPlacementTierS3::clear_params(const JSONFormattable& config) -{ - if (config.exists("endpoint")) { - endpoint.clear(); - } - if (config.exists("target_path")) { - target_path.clear(); - } - if (config.exists("region")) { - region.clear(); - } - if (config.exists("host_style")) { - /* default */ - host_style = PathStyle; - } - if (config.exists("target_storage_class")) { - target_storage_class.clear(); - } - if (config.exists("access_key")) { - key.id.clear(); - } - if (config.exists("secret")) { - key.key.clear(); - } - if (config.exists("multipart_sync_threshold")) { - multipart_sync_threshold = DEFAULT_MULTIPART_SYNC_PART_SIZE; - } - if (config.exists("multipart_min_part_size")) { - multipart_min_part_size = DEFAULT_MULTIPART_SYNC_PART_SIZE; - } - if (config.exists("acls")) { - const JSONFormattable& cc = config["acls"]; - if (cc.is_array()) { - for (auto& c : cc.array()) { - RGWTierACLMapping m; - m.init(c); - acl_mappings.erase(m.source_id); - } - } else { - RGWTierACLMapping m; - m.init(cc); - acl_mappings.erase(m.source_id); - } - } - return 0; -} - -int RGWZoneGroupTierS3Glacier::update_params(const JSONFormattable& config) -{ - int r = -1; - - if (config.exists("glacier_restore_days")) { - r = conf_to_uint64(config, "glacier_restore_days", &glacier_restore_days); - if (r < 0) { - glacier_restore_days = DEFAULT_GLACIER_RESTORE_DAYS; - } - } - if (config.exists("glacier_restore_tier_type")) { - string s; - s = config["glacier_restore_tier_type"]; - if (s != "Expedited") { - glacier_restore_tier_type = Standard; - } else { - glacier_restore_tier_type = Expedited; - } - } - return 0; -} - -int RGWZoneGroupTierS3Glacier::clear_params(const JSONFormattable& config) -{ - if (config.exists("glacier_restore_days")) { - glacier_restore_days = DEFAULT_GLACIER_RESTORE_DAYS; - } - if (config.exists("glacier_restore_tier_type")) { - /* default */ - glacier_restore_tier_type = Standard; - } - return 0; -} - -void rgw_meta_sync_info::generate_test_instances(list& o) -{ - auto info = new rgw_meta_sync_info; - info->state = rgw_meta_sync_info::StateBuildingFullSyncMaps; - info->period = "periodid"; - info->realm_epoch = 5; - o.push_back(info); - o.push_back(new rgw_meta_sync_info); -} - -void rgw_meta_sync_marker::generate_test_instances(list& o) -{ - auto marker = new rgw_meta_sync_marker; - marker->state = rgw_meta_sync_marker::IncrementalSync; - marker->marker = "01234"; - marker->realm_epoch = 5; - o.push_back(marker); - o.push_back(new rgw_meta_sync_marker); -} - -void rgw_meta_sync_status::generate_test_instances(list& o) -{ - o.push_back(new rgw_meta_sync_status); -} - -void RGWZoneParams::generate_test_instances(list &o) -{ - o.push_back(new RGWZoneParams); - o.push_back(new RGWZoneParams); -} - -void RGWPeriodLatestEpochInfo::generate_test_instances(list &o) -{ - RGWPeriodLatestEpochInfo *z = new RGWPeriodLatestEpochInfo; - o.push_back(z); - o.push_back(new RGWPeriodLatestEpochInfo); -} - -void RGWZoneGroup::generate_test_instances(list& o) -{ - RGWZoneGroup *r = new RGWZoneGroup; - o.push_back(r); - o.push_back(new RGWZoneGroup); -} - -void RGWPeriodLatestEpochInfo::dump(Formatter *f) const { - encode_json("latest_epoch", epoch, f); -} - -void RGWPeriodLatestEpochInfo::decode_json(JSONObj *obj) { - JSONDecoder::decode_json("latest_epoch", epoch, obj); -} - -void RGWNameToId::dump(Formatter *f) const { - encode_json("obj_id", obj_id, f); -} - -void RGWNameToId::decode_json(JSONObj *obj) { - JSONDecoder::decode_json("obj_id", obj_id, obj); -} - -void RGWNameToId::generate_test_instances(list& o) { - RGWNameToId *n = new RGWNameToId; - n->obj_id = "id"; - o.push_back(n); - o.push_back(new RGWNameToId); -} - diff --git a/src/rgw/radosgw-admin/radosgw-admin.cc b/src/rgw/radosgw-admin/radosgw-admin.cc index 33f33ebc76d..29927948be4 100644 --- a/src/rgw/radosgw-admin/radosgw-admin.cc +++ b/src/rgw/radosgw-admin/radosgw-admin.cc @@ -1988,7 +1988,7 @@ static int commit_period(rgw::sal::ConfigStore* cfgstore, RGWPeriod& period, string remote, const string& url, std::optional opt_region, const string& access, const string& secret, - bool force) + bool force, rgw::SiteConfig* site) { auto& master_zone = period.get_master_zone().id; if (master_zone.empty()) { @@ -2008,7 +2008,7 @@ static int commit_period(rgw::sal::ConfigStore* cfgstore, // the master zone can commit locally ret = rgw::commit_period(dpp(), null_yield, cfgstore, driver, realm, realm_writer, current_period, - period, cerr, force); + period, cerr, force, *site); if (ret < 0) { cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl; } @@ -2095,7 +2095,7 @@ static int update_period(rgw::sal::ConfigStore* cfgstore, const string& remote, const string& url, std::optional opt_region, const string& access, const string& secret, - Formatter *formatter, bool force) + Formatter *formatter, bool force, rgw::SiteConfig* site) { RGWRealm realm; std::unique_ptr realm_writer; @@ -2133,7 +2133,7 @@ static int update_period(rgw::sal::ConfigStore* cfgstore, } if (commit) { ret = commit_period(cfgstore, realm, *realm_writer, period, remote, url, - opt_region, access, secret, force); + opt_region, access, secret, force, site); if (ret < 0) { cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl; return ret; @@ -4890,7 +4890,7 @@ int main(int argc, const char **argv) int ret = update_period(cfgstore.get(), realm_id, realm_name, period_epoch, commit, remote, url, opt_region, access_key, secret_key, - formatter.get(), yes_i_really_mean_it); + formatter.get(), yes_i_really_mean_it, site.get()); if (ret < 0) { return -ret; } @@ -7040,7 +7040,7 @@ int main(int argc, const char **argv) int ret = update_period(cfgstore.get(), realm_id, realm_name, period_epoch, commit, remote, url, opt_region, access_key, secret_key, - formatter.get(), yes_i_really_mean_it); + formatter.get(), yes_i_really_mean_it, site.get()); if (ret < 0) { return -ret; } @@ -7069,7 +7069,7 @@ int main(int argc, const char **argv) } ret = commit_period(cfgstore.get(), realm, *realm_writer, period, remote, url, opt_region, access_key, secret_key, - yes_i_really_mean_it); + yes_i_really_mean_it, site.get()); if (ret < 0) { cerr << "failed to commit period: " << cpp_strerror(-ret) << std::endl; return -ret; diff --git a/src/rgw/rgw_appmain.cc b/src/rgw/rgw_appmain.cc index 3966ea6d212..82e48c62ae3 100644 --- a/src/rgw/rgw_appmain.cc +++ b/src/rgw/rgw_appmain.cc @@ -521,28 +521,33 @@ int rgw::AppMain::init_frontends2(RGWLib* rgwlib) /* ignore error */ } - // if we're part of a realm, add a watcher to respond to configuration changes - if (const auto& realm = env.site->get_realm(); realm) { - realm_watcher = env.cfgstore->create_realm_watcher(dpp, null_yield, *realm); - } - if (realm_watcher) { - pusher = std::make_unique(dpp, env.driver, env.cfgstore, null_yield); - realm_watcher->add_watcher(RGWRealmNotify::ZonesNeedPeriod, *pusher); - - fe_pauser = std::make_unique(fes, pusher.get()); - rgw_pauser = std::make_unique(); - rgw_pauser->add_pauser(fe_pauser.get()); - if (env.lua.background) { - rgw_pauser->add_pauser(env.lua.background); +#ifdef WITH_RADOSGW_RADOS + if (env.driver->get_name() == "rados") { + // add a watcher to respond to realm configuration changes + // if we're part of a realm, add a watcher to respond to configuration changes + if (const auto& realm = env.site->get_realm(); realm) { + realm_watcher = env.cfgstore->create_realm_watcher(dpp, null_yield, *realm); } + if (realm_watcher) { + pusher = std::make_unique(dpp, env.driver, env.cfgstore, null_yield); + realm_watcher->add_watcher(RGWRealmNotify::ZonesNeedPeriod, *pusher); + + fe_pauser = std::make_unique(fes, pusher.get()); + rgw_pauser = std::make_unique(); + rgw_pauser->add_pauser(fe_pauser.get()); + if (env.lua.background) { + rgw_pauser->add_pauser(env.lua.background); + } if (dedup_background) { rgw_pauser->add_pauser(dedup_background.get()); } - need_context_pool(); - reloader = std::make_unique( - env, *implicit_tenant_context, service_map_meta, rgw_pauser.get(), *context_pool); - realm_watcher->add_watcher(RGWRealmNotify::Reload, *reloader); + need_context_pool(); + reloader = std::make_unique( + env, *implicit_tenant_context, service_map_meta, rgw_pauser.get(), *context_pool); + realm_watcher->add_watcher(RGWRealmNotify::Reload, *reloader); + } } +#endif return r; } /* init_frontends2 */ @@ -576,6 +581,7 @@ void rgw::AppMain::init_lua() #endif env.lua.manager = env.driver->get_lua_manager(install_dir); +#ifdef WITH_RADOSGW_RADOS if (driver->get_name() == "rados") { /* Supported for only RadosStore */ lua_background = std::make_unique< rgw::lua::Background>(driver, dpp->get_cct(), env.lua.manager.get()); @@ -583,6 +589,7 @@ void rgw::AppMain::init_lua() env.lua.background = lua_background.get(); static_cast(env.lua.manager.get())->watch_reload(dpp); } +#endif } /* init_lua */ void rgw::AppMain::init_dedup() @@ -608,7 +615,7 @@ void rgw::AppMain::shutdown(std::function finalize_async_signals) realm_watcher.reset(); pusher.reset(); reloader.reset(); - +#ifdef WITH_RADOSGW_RADOS if (env.driver->get_name() == "rados") { if (g_conf().get_val("rgw_lua_enable")) static_cast(env.lua.manager.get())-> @@ -618,6 +625,7 @@ void rgw::AppMain::shutdown(std::function finalize_async_signals) dedup_background->unwatch_reload(dpp); } } +#endif for (auto& fe : fes) { fe->stop(); diff --git a/src/rgw/driver/rados/rgw_bucket_sync.cc b/src/rgw/rgw_bucket_sync.cc similarity index 100% rename from src/rgw/driver/rados/rgw_bucket_sync.cc rename to src/rgw/rgw_bucket_sync.cc diff --git a/src/rgw/driver/rados/rgw_bucket_sync.h b/src/rgw/rgw_bucket_sync.h similarity index 99% rename from src/rgw/driver/rados/rgw_bucket_sync.h rename to src/rgw/rgw_bucket_sync.h index d41bb4f3ee1..1ad93642943 100644 --- a/src/rgw/driver/rados/rgw_bucket_sync.h +++ b/src/rgw/rgw_bucket_sync.h @@ -18,6 +18,7 @@ #include "rgw_common.h" #include "rgw_sync_policy.h" +#include "rgw_zone.h" class RGWSI_Zone; class RGWSI_SyncModules; diff --git a/src/rgw/rgw_object_expirer.cc b/src/rgw/rgw_object_expirer.cc index 43540c1b8d2..d5831b93fbf 100644 --- a/src/rgw/rgw_object_expirer.cc +++ b/src/rgw/rgw_object_expirer.cc @@ -31,7 +31,7 @@ #include "rgw_formats.h" #include "rgw_usage.h" #include "rgw_object_expirer_core.h" -#include "driver/rados/rgw_zone.h" +#include "rgw_zone.h" #include "rgw_sal_config.h" #define dout_subsys ceph_subsys_rgw @@ -88,8 +88,7 @@ int main(const int argc, const char **argv) ceph::async::io_context_pool context_pool{cct->_conf->rgw_thread_pool_size}; const DoutPrefix dp(cct.get(), dout_subsys, "rgw object expirer: "); - DriverManager::Config cfg; - cfg.store_name = "rados"; + DriverManager::Config cfg = DriverManager::get_config(false, g_ceph_context); cfg.filter_name = "none"; std::unique_ptr cfgstore; auto config_store_type = g_conf().get_val("rgw_config_store"); diff --git a/src/rgw/rgw_period.cc b/src/rgw/rgw_period.cc index 242cb2eb1df..c3c5e2b48b5 100644 --- a/src/rgw/rgw_period.cc +++ b/src/rgw/rgw_period.cc @@ -13,6 +13,98 @@ std::string period_info_oid_prefix = "periods."; #define FIRST_EPOCH 1 +int RGWPeriod::get_zonegroup(RGWZoneGroup& zonegroup, + const string& zonegroup_id) const +{ + map::const_iterator iter; + if (!zonegroup_id.empty()) { + iter = period_map.zonegroups.find(zonegroup_id); + } else { + iter = period_map.zonegroups.find("default"); + } + if (iter != period_map.zonegroups.end()) { + zonegroup = iter->second; + return 0; + } + + return -ENOENT; +} + +static int read_sync_status(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver, rgw_meta_sync_status *sync_status) +{ + int r = -ENOTSUP; +#ifdef WITH_RADOSGW_RADOS + rgw::sal::RadosStore* rados_store = static_cast(driver); + // initialize a sync status manager to read the status + RGWMetaSyncStatusManager mgr(rados_store, rados_store->svc()->async_processor); + r = mgr.init(dpp); + if (r < 0) { + return r; + } + r = mgr.read_sync_status(dpp, sync_status); + mgr.stop(); +#endif + return r; +} + +int RGWPeriod::update_sync_status(const DoutPrefixProvider *dpp, + rgw::sal::Driver* driver, /* for now */ + const RGWPeriod ¤t_period, + std::ostream& error_stream, + bool force_if_stale) +{ + rgw_meta_sync_status status; + int r = read_sync_status(dpp, driver, &status); + if (r < 0) { + ldpp_dout(dpp, 0) << "period failed to read sync status: " + << cpp_strerror(-r) << dendl; + return r; + } + + std::vector markers; + + const auto current_epoch = current_period.get_realm_epoch(); + if (current_epoch != status.sync_info.realm_epoch) { + // no sync status markers for the current period + ceph_assert(current_epoch > status.sync_info.realm_epoch); + const int behind = current_epoch - status.sync_info.realm_epoch; + if (!force_if_stale && current_epoch > 1) { + error_stream << "ERROR: This zone is " << behind << " period(s) behind " + "the current master zone in metadata sync. If this zone is promoted " + "to master, any metadata changes during that time are likely to " + "be lost.\n" + "Waiting for this zone to catch up on metadata sync (see " + "'radosgw-admin sync status') is recommended.\n" + "To promote this zone to master anyway, add the flag " + "--yes-i-really-mean-it." << std::endl; + return -EINVAL; + } + // empty sync status markers - other zones will skip this period during + // incremental metadata sync + markers.resize(status.sync_info.num_shards); + } else { + markers.reserve(status.sync_info.num_shards); + for (auto& i : status.sync_markers) { + auto& marker = i.second; + // filter out markers from other periods + if (marker.realm_epoch != current_epoch) { + marker.marker.clear(); + } + markers.emplace_back(std::move(marker.marker)); + } + } + + std::swap(sync_status, markers); + return 0; +} + +void RGWPeriod::generate_test_instances(list &o) +{ + RGWPeriod *z = new RGWPeriod; + o.push_back(z); + o.push_back(new RGWPeriod); +} + const string& RGWPeriod::get_info_oid_prefix() const { return period_info_oid_prefix; diff --git a/src/rgw/rgw_realm_reloader.cc b/src/rgw/rgw_realm_reloader.cc index a586b19b815..c3c8ea78d90 100644 --- a/src/rgw/rgw_realm_reloader.cc +++ b/src/rgw/rgw_realm_reloader.cc @@ -118,8 +118,7 @@ void RGWRealmReloader::reload() ldpp_dout(&dp, 1) << "Creating new driver" << dendl; // recreate and initialize a new driver - DriverManager::Config cfg; - cfg.store_name = "rados"; + DriverManager::Config cfg = DriverManager::get_config(false, g_ceph_context); cfg.filter_name = "none"; env.driver = DriverManager::get_storage(&dp, cct, cfg, io_context, *env.site, diff --git a/src/rgw/rgw_rest_iam.cc b/src/rgw/rgw_rest_iam.cc index e074706a9dc..70d274946d2 100644 --- a/src/rgw/rgw_rest_iam.cc +++ b/src/rgw/rgw_rest_iam.cc @@ -13,7 +13,7 @@ #include "rgw_rest_iam_group.h" #include "rgw_rest_iam_user.h" #include "rgw_rest_conn.h" -#include "driver/rados/rgw_zone.h" +#include "rgw_zone.h" #define dout_context g_ceph_context #define dout_subsys ceph_subsys_rgw diff --git a/src/rgw/rgw_sal.cc b/src/rgw/rgw_sal.cc index 7195964ae8d..c11b5a80207 100644 --- a/src/rgw/rgw_sal.cc +++ b/src/rgw/rgw_sal.cc @@ -48,7 +48,9 @@ //#define dout_context g_ceph_context extern "C" { +#ifdef WITH_RADOSGW_RADOS extern rgw::sal::Driver* newRadosStore(boost::asio::io_context* io_context); +#endif #ifdef WITH_RADOSGW_DBSTORE extern rgw::sal::Driver* newDBStore(CephContext *cct); #endif @@ -86,6 +88,7 @@ rgw::sal::Driver* DriverManager::init_storage_provider(const DoutPrefixProvider* rgw::sal::Driver* driver{nullptr}; if (cfg.store_name.compare("rados") == 0) { +#ifdef WITH_RADOSGW_RADOS driver = newRadosStore(&io_context); RGWRados* rados = static_cast(driver)->getRados(); @@ -110,7 +113,9 @@ rgw::sal::Driver* DriverManager::init_storage_provider(const DoutPrefixProvider* delete driver; return nullptr; } +#endif } +#ifdef WITH_RADOSGW_RADOS else if (cfg.store_name.compare("d3n") == 0) { driver = new rgw::sal::RadosStore(io_context); RGWRados* rados = new D3nRGWDataCache; @@ -151,6 +156,7 @@ rgw::sal::Driver* DriverManager::init_storage_provider(const DoutPrefixProvider* lsubdout(cct, rgw, 1) << "rgw_d3n: rgw_d3n_l1_eviction_policy=" << cct->_conf->rgw_d3n_l1_eviction_policy << dendl; } +#endif #ifdef WITH_RADOSGW_DBSTORE else if (cfg.store_name.compare("dbstore") == 0) { driver = newDBStore(cct); @@ -238,6 +244,7 @@ rgw::sal::Driver* DriverManager::init_raw_storage_provider(const DoutPrefixProvi { rgw::sal::Driver* driver = nullptr; if (cfg.store_name.compare("rados") == 0) { +#ifdef WITH_RADOSGW_RADOS driver = newRadosStore(&io_context); RGWRados* rados = static_cast(driver)->getRados(); @@ -259,6 +266,7 @@ rgw::sal::Driver* DriverManager::init_raw_storage_provider(const DoutPrefixProvi delete driver; return nullptr; } +#endif } else if (cfg.store_name.compare("dbstore") == 0) { #ifdef WITH_RADOSGW_DBSTORE driver = newDBStore(cct); @@ -320,6 +328,7 @@ DriverManager::Config DriverManager::get_config(bool admin, CephContext* cct) // Get the store backend const auto& config_store = g_conf().get_val("rgw_backend_store"); if (config_store == "rados") { +#ifdef WITH_RADOSGW_RADOS cfg.store_name = "rados"; /* Check to see if d3n is configured, but only for non-admin */ @@ -334,6 +343,7 @@ DriverManager::Config DriverManager::get_config(bool admin, CephContext* cct) cfg.store_name = "d3n"; } } +#endif } #ifdef WITH_RADOSGW_DBSTORE else if (config_store == "dbstore") { @@ -373,14 +383,18 @@ auto DriverManager::create_config_store(const DoutPrefixProvider* dpp, -> std::unique_ptr { try { +#ifdef WITH_RADOSGW_RADOS if (type == "rados") { return rgw::rados::create_config_store(dpp); + } +#endif #ifdef WITH_RADOSGW_DBSTORE - } else if (type == "dbstore") { + if (type == "dbstore") { const auto uri = g_conf().get_val("dbstore_config_uri"); return rgw::dbstore::create_config_store(dpp, uri); + } #endif - } else if (type == "json") { + if (type == "json") { auto filename = g_conf().get_val("rgw_json_config"); return rgw::sal::create_json_config_store(dpp, filename); } else { diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index 6636d8bea19..ee8d101f3ec 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -110,3 +110,65 @@ void rgw_get_anon_user(RGWUserInfo& info) info.access_keys.clear(); } +static bool char_is_unreserved_url(char c) +{ + if (isalnum(c)) + return true; + + switch (c) { + case '-': + case '.': + case '_': + case '~': + return true; + default: + return false; + } +} + +static bool validate_access_key(string& key) +{ + const char *p = key.c_str(); + while (*p) { + if (!char_is_unreserved_url(*p)) + return false; + p++; + } + return true; +} + +int rgw_generate_access_key(const DoutPrefixProvider* dpp, + optional_yield y, + rgw::sal::Driver* driver, + std::string& access_key_id) +{ + std::string id; + int r = 0; + + do { + id.resize(PUBLIC_ID_LEN + 1); + gen_rand_alphanumeric_upper(dpp->get_cct(), id.data(), id.size()); + id.pop_back(); // remove trailing null + + if (!validate_access_key(id)) + continue; + + std::unique_ptr duplicate_check; + r = driver->get_user_by_access_key(dpp, id, y, &duplicate_check); + } while (r == 0); + + if (r == -ENOENT) { + access_key_id = std::move(id); + return 0; + } + return r; +} + +void rgw_generate_secret_key(CephContext* cct, + std::string& secret_key) +{ + char secret_key_buf[SECRET_KEY_LEN + 1]; + gen_rand_alphanumeric_plain(cct, secret_key_buf, sizeof(secret_key_buf)); + secret_key = secret_key_buf; +} + diff --git a/src/rgw/rgw_zone.cc b/src/rgw/rgw_zone.cc index 9ec69c1fa2c..4e0fddabb3c 100644 --- a/src/rgw/rgw_zone.cc +++ b/src/rgw/rgw_zone.cc @@ -16,6 +16,12 @@ #define dout_context g_ceph_context #define dout_subsys ceph_subsys_rgw +RGWMetaSyncStatusManager::~RGWMetaSyncStatusManager(){} + +#define FIRST_EPOCH 1 + +struct RGWAccessKey; + namespace rgw_zone_defaults { static std::string default_bucket_index_pool_suffix = "rgw.buckets.index"; @@ -259,7 +265,148 @@ void add_zone_pools(const RGWZoneParams& info, } } +void RGWDefaultZoneGroupInfo::dump(Formatter *f) const { + encode_json("default_zonegroup", default_zonegroup, f); +} + +void RGWDefaultZoneGroupInfo::decode_json(JSONObj *obj) { + + JSONDecoder::decode_json("default_zonegroup", default_zonegroup, obj); + /* backward compatability with region */ + if (default_zonegroup.empty()) { + JSONDecoder::decode_json("default_region", default_zonegroup, obj); + } +} + +int RGWZoneGroup::equals(const string& other_zonegroup) const +{ + if (is_master && other_zonegroup.empty()) + return true; + + return (id == other_zonegroup); +} + +void RGWDefaultSystemMetaObjInfo::dump(Formatter *f) const { + encode_json("default_id", default_id, f); +} + +void RGWDefaultSystemMetaObjInfo::decode_json(JSONObj *obj) { + JSONDecoder::decode_json("default_id", default_id, obj); +} + +const string& RGWZoneParams::get_compression_type(const rgw_placement_rule& placement_rule) const +{ + static const std::string NONE{"none"}; + auto p = placement_pools.find(placement_rule.name); + if (p == placement_pools.end()) { + return NONE; + } + const auto& type = p->second.get_compression_type(placement_rule.get_storage_class()); + return !type.empty() ? type : NONE; +} + +// run an MD5 hash on the zone_id and return the first 32 bits +static uint32_t gen_short_zone_id(const std::string zone_id) +{ + unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE]; + MD5 hash; + // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes + hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + hash.Update((const unsigned char *)zone_id.c_str(), zone_id.size()); + hash.Final(md5); + + uint32_t short_id; + memcpy((char *)&short_id, md5, sizeof(short_id)); + return std::max(short_id, 1u); +} + +int RGWPeriodMap::update(const RGWZoneGroup& zonegroup, CephContext *cct) +{ + if (zonegroup.is_master_zonegroup() && (!master_zonegroup.empty() && zonegroup.get_id() != master_zonegroup)) { + ldout(cct,0) << "Error updating periodmap, multiple master zonegroups configured "<< dendl; + ldout(cct,0) << "master zonegroup: " << master_zonegroup << " and " << zonegroup.get_id() <::iterator iter = zonegroups.find(zonegroup.get_id()); + if (iter != zonegroups.end()) { + RGWZoneGroup& old_zonegroup = iter->second; + if (!old_zonegroup.api_name.empty()) { + zonegroups_by_api.erase(old_zonegroup.api_name); + } + } + zonegroups[zonegroup.get_id()] = zonegroup; + + if (!zonegroup.api_name.empty()) { + zonegroups_by_api[zonegroup.api_name] = zonegroup; + } + + if (zonegroup.is_master_zonegroup()) { + master_zonegroup = zonegroup.get_id(); + } else if (master_zonegroup == zonegroup.get_id()) { + master_zonegroup = ""; + } + + for (auto& i : zonegroup.zones) { + auto& zone = i.second; + if (short_zone_ids.find(zone.id) != short_zone_ids.end()) { + continue; + } + // calculate the zone's short id + uint32_t short_id = gen_short_zone_id(zone.id); + + // search for an existing zone with the same short id + for (auto& s : short_zone_ids) { + if (s.second == short_id) { + ldout(cct, 0) << "New zone '" << zone.name << "' (" << zone.id + << ") generates the same short_zone_id " << short_id + << " as existing zone id " << s.first << dendl; + return -EEXIST; + } + } + + short_zone_ids[zone.id] = short_id; + } + + return 0; +} + +uint32_t RGWPeriodMap::get_zone_short_id(const string& zone_id) const +{ + auto i = short_zone_ids.find(zone_id); + if (i == short_zone_ids.end()) { + return 0; + } + return i->second; +} + +bool RGWPeriodMap::find_zone_by_name(const string& zone_name, + RGWZoneGroup *zonegroup, + RGWZone *zone) const +{ + for (auto& iter : zonegroups) { + auto& zg = iter.second; + for (auto& ziter : zg.zones) { + auto& z = ziter.second; + + if (z.name == zone_name) { + *zonegroup = zg; + *zone = z; + return true; + } + } + } + + return false; +} + namespace rgw { +/// Generate a random uuid for realm/period/zonegroup/zone ids +std::string gen_random_uuid() +{ + uuid_d uuid; + uuid.generate_random(); + return uuid.to_string(); +} int get_zones_pool_set(const DoutPrefixProvider *dpp, optional_yield y, @@ -829,5 +976,1168 @@ int add_zone_to_group(const DoutPrefixProvider* dpp, RGWZoneGroup& zonegroup, return 0; } +int read_realm(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, + std::string_view realm_id, + std::string_view realm_name, + RGWRealm& info, + std::unique_ptr* writer) +{ + if (!realm_id.empty()) { + return cfgstore->read_realm_by_id(dpp, y, realm_id, info, writer); + } + if (!realm_name.empty()) { + return cfgstore->read_realm_by_name(dpp, y, realm_name, info, writer); + } + return cfgstore->read_default_realm(dpp, y, info, writer); +} + +int create_realm(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, bool exclusive, + RGWRealm& info, + std::unique_ptr* writer_out) +{ + if (info.name.empty()) { + ldpp_dout(dpp, -1) << __func__ << " requires a realm name" << dendl; + return -EINVAL; + } + if (info.id.empty()) { + info.id = gen_random_uuid(); + } + + // if the realm already has a current_period, just make sure it exists + std::optional period; + if (!info.current_period.empty()) { + period.emplace(); + int r = cfgstore->read_period(dpp, y, info.current_period, + std::nullopt, *period); + if (r < 0) { + ldpp_dout(dpp, -1) << __func__ << " failed to read realm's current_period=" + << info.current_period << " with " << cpp_strerror(r) << dendl; + return r; + } + } + + // create the realm + std::unique_ptr writer; + int r = cfgstore->create_realm(dpp, y, exclusive, info, &writer); + if (r < 0) { + return r; + } + + if (!period) { + // initialize and exclusive-create the initial period + period.emplace(); + period->id = gen_random_uuid(); + period->period_map.id = period->id; + period->epoch = FIRST_EPOCH; + period->realm_id = info.id; + + r = cfgstore->create_period(dpp, y, true, *period); + if (r < 0) { + ldpp_dout(dpp, -1) << __func__ << " failed to create the initial period id=" + << period->id << " for realm " << info.name + << " with " << cpp_strerror(r) << dendl; + return r; + } + } + + // update the realm's current_period + r = realm_set_current_period(dpp, y, cfgstore, *writer, info, *period); + if (r < 0) { + return r; + } + + if (writer_out) { + *writer_out = std::move(writer); + } + return 0; +} + +int set_default_realm(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, const RGWRealm& info, + bool exclusive) +{ + return cfgstore->write_default_realm_id(dpp, y, exclusive, info.id); +} + +int realm_set_current_period(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, + sal::RealmWriter& writer, RGWRealm& realm, + const RGWPeriod& period) +{ + // update realm epoch to match the period's + if (realm.epoch > period.realm_epoch) { + ldpp_dout(dpp, -1) << __func__ << " with old realm epoch " + << period.realm_epoch << ", current epoch=" << realm.epoch << dendl; + return -EINVAL; + } + if (realm.epoch == period.realm_epoch && realm.current_period != period.id) { + ldpp_dout(dpp, -1) << __func__ << " with same realm epoch " + << period.realm_epoch << ", but different period id " + << period.id << " != " << realm.current_period << dendl; + return -EINVAL; + } + + realm.epoch = period.realm_epoch; + realm.current_period = period.id; + + // update the realm object + int r = writer.write(dpp, y, realm); + if (r < 0) { + ldpp_dout(dpp, -1) << __func__ << " failed to overwrite realm " + << realm.name << " with " << cpp_strerror(r) << dendl; + return r; + } + + // reflect the zonegroup and period config + (void) reflect_period(dpp, y, cfgstore, period); + return 0; +} + +int reflect_period(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, const RGWPeriod& info) +{ + // overwrite the local period config and zonegroup objects + constexpr bool exclusive = false; + + int r = cfgstore->write_period_config(dpp, y, exclusive, info.realm_id, + info.period_config); + if (r < 0) { + ldpp_dout(dpp, -1) << __func__ << " failed to store period config for realm id=" + << info.realm_id << " with " << cpp_strerror(r) << dendl; + return r; + } + + for (auto& [zonegroup_id, zonegroup] : info.period_map.zonegroups) { + r = cfgstore->create_zonegroup(dpp, y, exclusive, zonegroup, nullptr); + if (r < 0) { + ldpp_dout(dpp, -1) << __func__ << " failed to store zonegroup id=" + << zonegroup_id << " with " << cpp_strerror(r) << dendl; + return r; + } + if (zonegroup.is_master) { + // set master as default if no default exists + constexpr bool exclusive = true; + r = set_default_zonegroup(dpp, y, cfgstore, zonegroup, exclusive); + if (r == 0) { + ldpp_dout(dpp, 1) << "Set the period's master zonegroup " + << zonegroup.name << " as the default" << dendl; + } + } + } + return 0; +} + +std::string get_staging_period_id(std::string_view realm_id) +{ + return string_cat_reserve(realm_id, ":staging"); +} + +void fork_period(const DoutPrefixProvider* dpp, RGWPeriod& info) +{ + ldpp_dout(dpp, 20) << __func__ << " realm id=" << info.realm_id + << " period id=" << info.id << dendl; + + info.predecessor_uuid = std::move(info.id); + info.id = get_staging_period_id(info.realm_id); + info.period_map.reset(); + info.realm_epoch++; +} + +int update_period(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, RGWPeriod& info) +{ + // clear zone short ids of removed zones. period_map.update() will add the + // remaining zones back + info.period_map.short_zone_ids.clear(); + + // list all zonegroups in the realm + rgw::sal::ListResult listing; + std::array zonegroup_names; // list in pages of 1000 + do { + int ret = cfgstore->list_zonegroup_names(dpp, y, listing.next, + zonegroup_names, listing); + if (ret < 0) { + std::cerr << "failed to list zonegroups: " << cpp_strerror(-ret) << std::endl; + return -ret; + } + for (const auto& name : listing.entries) { + RGWZoneGroup zg; + ret = cfgstore->read_zonegroup_by_name(dpp, y, name, zg, nullptr); + if (ret < 0) { + ldpp_dout(dpp, 0) << "WARNING: failed to read zonegroup " + << name << ": " << cpp_strerror(-ret) << dendl; + continue; + } + + if (zg.realm_id != info.realm_id) { + ldpp_dout(dpp, 20) << "skipping zonegroup " << zg.get_name() + << " with realm id " << zg.realm_id + << ", not on our realm " << info.realm_id << dendl; + continue; + } + + if (zg.master_zone.empty()) { + ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name() << " should have a master zone " << dendl; + return -EINVAL; + } + + if (zg.zones.find(zg.master_zone) == zg.zones.end()) { + ldpp_dout(dpp, 0) << "ERROR: zonegroup " << zg.get_name() + << " has a non existent master zone "<< dendl; + return -EINVAL; + } + + if (zg.is_master_zonegroup()) { + info.master_zonegroup = zg.get_id(); + info.master_zone = zg.master_zone; + } + + ret = info.period_map.update(zg, dpp->get_cct()); + if (ret < 0) { + return ret; + } + } // foreach name in listing.entries + } while (!listing.next.empty()); + + // read the realm's current period config + int ret = cfgstore->read_period_config(dpp, y, info.realm_id, + info.period_config); + if (ret < 0 && ret != -ENOENT) { + ldpp_dout(dpp, 0) << "ERROR: failed to read period config: " + << cpp_strerror(ret) << dendl; + return ret; + } + + return 0; +} + +int commit_period(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, sal::Driver* driver, + RGWRealm& realm, sal::RealmWriter& realm_writer, + const RGWPeriod& current_period, + RGWPeriod& info, std::ostream& error_stream, + bool force_if_stale, const rgw::SiteConfig& site) +{ + ldpp_dout(dpp, 20) << __func__ << " realm " << realm.id + << " period " << current_period.id << dendl; + + // gateway must be in the master zone to commit + if (info.master_zone != site.get_zone_params().id) { + error_stream << "Cannot commit period on zone " + << site.get_zone_params().id << ", it must be sent to " + "the period's master zone " << info.master_zone << '.' << std::endl; + return -EINVAL; + } + // period predecessor must match current period + if (info.predecessor_uuid != current_period.id) { + error_stream << "Period predecessor " << info.predecessor_uuid + << " does not match current period " << current_period.id + << ". Use 'period pull' to get the latest period from the master, " + "reapply your changes, and try again." << std::endl; + return -EINVAL; + } + // realm epoch must be 1 greater than current period + if (info.realm_epoch != current_period.realm_epoch + 1) { + error_stream << "Period's realm epoch " << info.realm_epoch + << " does not come directly after current realm epoch " + << current_period.realm_epoch << ". Use 'realm pull' to get the " + "latest realm and period from the master zone, reapply your changes, " + "and try again." << std::endl; + return -EINVAL; + } + // did the master zone change? + if (info.master_zone != current_period.master_zone) { + // store the current metadata sync status in the period + int r = info.update_sync_status(dpp, driver, current_period, + error_stream, force_if_stale); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to update metadata sync status: " + << cpp_strerror(-r) << dendl; + return r; + } + // create an object with a new period id + info.period_map.id = info.id = gen_random_uuid(); + info.epoch = FIRST_EPOCH; + + constexpr bool exclusive = true; + r = cfgstore->create_period(dpp, y, exclusive, info); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to create new period: " << cpp_strerror(-r) << dendl; + return r; + } + // set as current period + r = realm_set_current_period(dpp, y, cfgstore, realm_writer, realm, info); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to update realm's current period: " + << cpp_strerror(-r) << dendl; + return r; + } + ldpp_dout(dpp, 4) << "Promoted to master zone and committed new period " + << info.id << dendl; + return 0; + } + // period must be based on current epoch + if (info.epoch != current_period.epoch) { + error_stream << "Period epoch " << info.epoch << " does not match " + "predecessor epoch " << current_period.epoch << ". Use " + "'period pull' to get the latest epoch from the master zone, " + "reapply your changes, and try again." << std::endl; + return -EINVAL; + } + // set period as next epoch + info.id = current_period.id; + info.epoch = current_period.epoch + 1; + info.predecessor_uuid = current_period.predecessor_uuid; + info.realm_epoch = current_period.realm_epoch; + // write the period + constexpr bool exclusive = true; + int r = cfgstore->create_period(dpp, y, exclusive, info); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to store period: " << cpp_strerror(r) << dendl; + return r; + } + r = reflect_period(dpp, y, cfgstore, info); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to update local objects: " << cpp_strerror(r) << dendl; + return r; + } + ldpp_dout(dpp, 4) << "Committed new epoch " << info.epoch + << " for period " << info.id << dendl; + return 0; +} + + +int read_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, + std::string_view zonegroup_id, + std::string_view zonegroup_name, + RGWZoneGroup& info, + std::unique_ptr* writer) +{ + if (!zonegroup_id.empty()) { + return cfgstore->read_zonegroup_by_id(dpp, y, zonegroup_id, info, writer); + } + if (!zonegroup_name.empty()) { + return cfgstore->read_zonegroup_by_name(dpp, y, zonegroup_name, info, writer); + } + + std::string realm_id; + int r = cfgstore->read_default_realm_id(dpp, y, realm_id); + if (r == -ENOENT) { + return cfgstore->read_zonegroup_by_name(dpp, y, default_zonegroup_name, + info, writer); + } + if (r < 0) { + return r; + } + return cfgstore->read_default_zonegroup(dpp, y, realm_id, info, writer); +} + +int create_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, bool exclusive, + RGWZoneGroup& info) +{ + if (info.name.empty()) { + ldpp_dout(dpp, -1) << __func__ << " requires a zonegroup name" << dendl; + return -EINVAL; + } + if (info.id.empty()) { + info.id = gen_random_uuid(); + } + + // insert the default placement target if it doesn't exist + constexpr std::string_view default_placement_name = "default-placement"; + + RGWZoneGroupPlacementTarget placement_target; + placement_target.name = default_placement_name; + + info.placement_targets.emplace(default_placement_name, placement_target); + if (info.default_placement.name.empty()) { + info.default_placement.name = default_placement_name; + } + + int r = cfgstore->create_zonegroup(dpp, y, exclusive, info, nullptr); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to create zonegroup with " + << cpp_strerror(r) << dendl; + return r; + } + + // try to set as default. may race with another create, so pass exclusive=true + // so we don't override an existing default + r = set_default_zonegroup(dpp, y, cfgstore, info, true); + if (r < 0 && r != -EEXIST) { + ldpp_dout(dpp, 0) << "WARNING: failed to set zonegroup as default: " + << cpp_strerror(r) << dendl; + } + + return 0; +} + +static int create_default_zonegroup(const DoutPrefixProvider* dpp, + optional_yield y, + sal::ConfigStore* cfgstore, + bool exclusive, + const RGWZoneParams& default_zone, + RGWZoneGroup& info) +{ + info.name = default_zonegroup_name; + info.api_name = default_zonegroup_name; + info.is_master = true; + + // enable all supported features + info.enabled_features.insert(rgw::zone_features::enabled.begin(), + rgw::zone_features::enabled.end()); + + // add the zone to the zonegroup + bool is_master = true; + std::list empty_list; + rgw::zone_features::set disable_features; // empty + int r = add_zone_to_group(dpp, info, default_zone, &is_master, nullptr, + empty_list, nullptr, nullptr, empty_list, + empty_list, nullptr, std::nullopt, + info.enabled_features, disable_features); + if (r < 0) { + return r; + } + + // write the zone + return create_zonegroup(dpp, y, cfgstore, exclusive, info); +} + +int set_default_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, const RGWZoneGroup& info, + bool exclusive) +{ + return cfgstore->write_default_zonegroup_id( + dpp, y, exclusive, info.realm_id, info.id); +} + +int remove_zone_from_group(const DoutPrefixProvider* dpp, + RGWZoneGroup& zonegroup, + const rgw_zone_id& zone_id) +{ + auto z = zonegroup.zones.find(zone_id); + if (z == zonegroup.zones.end()) { + return -ENOENT; + } + zonegroup.zones.erase(z); + + if (zonegroup.master_zone == zone_id) { + // choose a new master zone + auto m = zonegroup.zones.begin(); + if (m != zonegroup.zones.end()) { + zonegroup.master_zone = m->first; + ldpp_dout(dpp, 0) << "NOTICE: promoted " << m->second.name + << " as new master_zone of zonegroup " << zonegroup.name << dendl; + } else { + ldpp_dout(dpp, 0) << "NOTICE: removed master_zone of zonegroup " + << zonegroup.name << dendl; + } + } + + const bool log_data = zonegroup.zones.size() > 1; + for (auto& [id, zone] : zonegroup.zones) { + zone.log_data = log_data; + } + + return 0; +} + +// try to remove the given zone id from every zonegroup in the cluster +static int remove_zone_from_groups(const DoutPrefixProvider* dpp, + optional_yield y, + sal::ConfigStore* cfgstore, + const rgw_zone_id& zone_id) +{ + std::array zonegroup_names; + sal::ListResult listing; + do { + int r = cfgstore->list_zonegroup_names(dpp, y, listing.next, + zonegroup_names, listing); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to list zonegroups with " + << cpp_strerror(r) << dendl; + return r; + } + + for (const auto& name : listing.entries) { + RGWZoneGroup zonegroup; + std::unique_ptr writer; + r = cfgstore->read_zonegroup_by_name(dpp, y, name, zonegroup, &writer); + if (r < 0) { + ldpp_dout(dpp, 0) << "WARNING: failed to load zonegroup " << name + << " with " << cpp_strerror(r) << dendl; + continue; + } + + r = remove_zone_from_group(dpp, zonegroup, zone_id); + if (r < 0) { + continue; + } + + // write the updated zonegroup + r = writer->write(dpp, y, zonegroup); + if (r < 0) { + ldpp_dout(dpp, 0) << "WARNING: failed to write zonegroup " << name + << " with " << cpp_strerror(r) << dendl; + continue; + } + ldpp_dout(dpp, 0) << "Removed zone from zonegroup " << name << dendl; + } + } while (!listing.next.empty()); + + return 0; +} + + +int read_zone(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, + std::string_view zone_id, + std::string_view zone_name, + RGWZoneParams& info, + std::unique_ptr* writer) +{ + if (!zone_id.empty()) { + return cfgstore->read_zone_by_id(dpp, y, zone_id, info, writer); + } + if (!zone_name.empty()) { + return cfgstore->read_zone_by_name(dpp, y, zone_name, info, writer); + } + + std::string realm_id; + int r = cfgstore->read_default_realm_id(dpp, y, realm_id); + if (r == -ENOENT) { + return cfgstore->read_zone_by_name(dpp, y, default_zone_name, info, writer); + } + if (r < 0) { + return r; + } + return cfgstore->read_default_zone(dpp, y, realm_id, info, writer); +} + +extern int get_zones_pool_set(const DoutPrefixProvider *dpp, optional_yield y, + rgw::sal::ConfigStore* cfgstore, + std::string_view my_zone_id, + std::set& pools); + +int create_zone(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, bool exclusive, + RGWZoneParams& info, std::unique_ptr* writer) +{ + if (info.name.empty()) { + ldpp_dout(dpp, -1) << __func__ << " requires a zone name" << dendl; + return -EINVAL; + } + if (info.id.empty()) { + info.id = gen_random_uuid(); + } + + // add default placement with empty pool name + RGWZonePlacementInfo placement; + rgw_pool pool; + placement.storage_classes.set_storage_class( + RGW_STORAGE_CLASS_STANDARD, &pool, nullptr); + // don't overwrite if it already exists + info.placement_pools.emplace("default-placement", std::move(placement)); + + // build a set of all pool names used by other zones + std::set pools; + int r = get_zones_pool_set(dpp, y, cfgstore, info.id, pools); + if (r < 0) { + return r; + } + + // initialize pool names with the zone name prefix + r = init_zone_pool_names(dpp, y, pools, info); + if (r < 0) { + return r; + } + + r = cfgstore->create_zone(dpp, y, exclusive, info, nullptr); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to create zone with " + << cpp_strerror(r) << dendl; + return r; + } + + // try to set as default. may race with another create, so pass exclusive=true + // so we don't override an existing default + r = set_default_zone(dpp, y, cfgstore, info, true); + if (r < 0 && r != -EEXIST) { + ldpp_dout(dpp, 0) << "WARNING: failed to set zone as default: " + << cpp_strerror(r) << dendl; + } + + return 0; + +} + +int set_default_zone(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, const RGWZoneParams& info, + bool exclusive) +{ + return cfgstore->write_default_zone_id( + dpp, y, exclusive, info.realm_id, info.id); +} + +int delete_zone(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, const RGWZoneParams& info, + sal::ZoneWriter& writer) +{ + // remove this zone from any zonegroups that contain it + int r = remove_zone_from_groups(dpp, y, cfgstore, info.id); + if (r < 0) { + return r; + } + + return writer.remove(dpp, y); +} + +auto find_zone_placement(const DoutPrefixProvider* dpp, + const RGWZoneParams& info, + const rgw_placement_rule& rule) + -> const RGWZonePlacementInfo* +{ + auto i = info.placement_pools.find(rule.name); + if (i == info.placement_pools.end()) { + ldpp_dout(dpp, 0) << "ERROR: This zone does not contain placement rule " + << rule.name << dendl; + return nullptr; + } + + const std::string& storage_class = rule.get_storage_class(); + if (!i->second.storage_class_exists(storage_class)) { + ldpp_dout(dpp, 5) << "ERROR: The zone placement for rule " << rule.name + << " does not contain storage class " << storage_class << dendl; + return nullptr; + } + + return &i->second; +} + +bool all_zonegroups_support(const SiteConfig& site, std::string_view feature) +{ + const auto& period = site.get_period(); + if (!period) { + // if we're not in a realm, just check the local zonegroup + return site.get_zonegroup().supports(feature); + } + const auto& zgs = period->period_map.zonegroups; + return std::all_of(zgs.begin(), zgs.end(), [feature] (const auto& pair) { + return pair.second.supports(feature); + }); +} + +static int read_or_create_default_zone(const DoutPrefixProvider* dpp, + optional_yield y, + sal::ConfigStore* cfgstore, + RGWZoneParams& info) +{ + int r = cfgstore->read_zone_by_name(dpp, y, default_zone_name, info, nullptr); + if (r == -ENOENT) { + info.name = default_zone_name; + constexpr bool exclusive = true; + r = create_zone(dpp, y, cfgstore, exclusive, info, nullptr); + if (r == -EEXIST) { + r = cfgstore->read_zone_by_name(dpp, y, default_zone_name, info, nullptr); + } + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to create default zone: " + << cpp_strerror(r) << dendl; + return r; + } + } + return r; +} + +static int read_or_create_default_zonegroup(const DoutPrefixProvider* dpp, + optional_yield y, + sal::ConfigStore* cfgstore, + const RGWZoneParams& zone_params, + RGWZoneGroup& info) +{ + int r = cfgstore->read_zonegroup_by_name(dpp, y, default_zonegroup_name, + info, nullptr); + if (r == -ENOENT) { + constexpr bool exclusive = true; + r = create_default_zonegroup(dpp, y, cfgstore, exclusive, + zone_params, info); + if (r == -EEXIST) { + r = cfgstore->read_zonegroup_by_name(dpp, y, default_zonegroup_name, + info, nullptr); + } + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to create default zonegroup: " + << cpp_strerror(r) << dendl; + return r; + } + } + return r; +} + +int SiteConfig::load(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, bool force_local_zonegroup) +{ + // clear existing configuration + zone = nullptr; + zonegroup = nullptr; + local_zonegroup = std::nullopt; + period = std::nullopt; + zone_params = RGWZoneParams{}; + + int r = 0; + + // try to load a realm + realm.emplace(); + std::string realm_name = dpp->get_cct()->_conf->rgw_realm; + if (!realm_name.empty()) { + r = cfgstore->read_realm_by_name(dpp, y, realm_name, *realm, nullptr); + } else { + r = cfgstore->read_default_realm(dpp, y, *realm, nullptr); + if (r == -ENOENT) { // no realm + r = 0; + realm = std::nullopt; + } + } + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to load realm: " << cpp_strerror(r) << dendl; + return r; + } + + // try to load the local zone params + std::string zone_name = dpp->get_cct()->_conf->rgw_zone; + if (!zone_name.empty()) { + r = cfgstore->read_zone_by_name(dpp, y, zone_name, zone_params, nullptr); + } else if (realm) { + // load the realm's default zone + r = cfgstore->read_default_zone(dpp, y, realm->id, zone_params, nullptr); + if (r == -ENOENT) { + if (realm_name.empty()) { + // rgw_realm was not specified, and we found a default realm that + // doesn't have a default zone. ignore the realm and try to load the + // global default zone + realm = std::nullopt; + r = read_or_create_default_zone(dpp, y, cfgstore, zone_params); + } else { + ldpp_dout(dpp, 0) << "No rgw_zone configured, and the selected realm \"" + << realm->name << "\" does not have a default zone." << dendl; + } + } + } else { + // load or create the "default" zone + r = read_or_create_default_zone(dpp, y, cfgstore, zone_params); + } + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to load zone: " << cpp_strerror(r) << dendl; + return r; + } + + if (!realm && !zone_params.realm_id.empty()) { + realm.emplace(); + r = cfgstore->read_realm_by_id(dpp, y, zone_params.realm_id, + *realm, nullptr); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to load realm: " << cpp_strerror(r) << dendl; + return r; + } + } + + if (realm && !force_local_zonegroup) { + // try to load the realm's period + r = load_period_zonegroup(dpp, y, cfgstore, *realm, zone_params.id); + if (r != -ENOENT) { + return r; + } + ldpp_dout(dpp, 10) << "cannot find current period zonegroup, " + "using local zonegroup configuration" << dendl; + } + + // fall back to a local zonegroup + return load_local_zonegroup(dpp, y, cfgstore, zone_params.id); +} + +std::unique_ptr SiteConfig::make_fake() { + auto fake = std::make_unique(); + fake->local_zonegroup.emplace(); + fake->local_zonegroup->zones.emplace(""s, RGWZone{}); + fake->zonegroup = &*fake->local_zonegroup; + fake->zone = &fake->zonegroup->zones.begin()->second; + return fake; +} + +int SiteConfig::load_period_zonegroup(const DoutPrefixProvider* dpp, + optional_yield y, + sal::ConfigStore* cfgstore, + const RGWRealm& realm, + const rgw_zone_id& zone_id) +{ + // load the realm's current period + period.emplace(); + int r = cfgstore->read_period(dpp, y, realm.current_period, + std::nullopt, *period); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to load current period: " + << cpp_strerror(r) << dendl; + return r; + } + + // find our zone and zonegroup in the period + for (const auto& zg : period->period_map.zonegroups) { + auto z = zg.second.zones.find(zone_id); + if (z != zg.second.zones.end()) { + zone = &z->second; + zonegroup = &zg.second; + return 0; + } + } + + ldpp_dout(dpp, 0) << "ERROR: current period " << period->id + << " does not contain zone id " << zone_id << dendl; + + period = std::nullopt; + return -ENOENT; +} + +int SiteConfig::load_local_zonegroup(const DoutPrefixProvider* dpp, + optional_yield y, + sal::ConfigStore* cfgstore, + const rgw_zone_id& zone_id) +{ + int r = 0; + + // load the zonegroup + local_zonegroup.emplace(); + std::string zonegroup_name = dpp->get_cct()->_conf->rgw_zonegroup; + if (!zonegroup_name.empty()) { + r = cfgstore->read_zonegroup_by_name(dpp, y, zonegroup_name, + *local_zonegroup, nullptr); + } else if (realm) { + r = cfgstore->read_default_zonegroup(dpp, y, realm->id, + *local_zonegroup, nullptr); + } else { + r = read_or_create_default_zonegroup(dpp, y, cfgstore, zone_params, + *local_zonegroup); + } + + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to load zonegroup: " + << cpp_strerror(r) << dendl; + } else { + // find our zone in the zonegroup + auto z = local_zonegroup->zones.find(zone_id); + if (z != local_zonegroup->zones.end()) { + zone = &z->second; + zonegroup = &*local_zonegroup; + return 0; + } + ldpp_dout(dpp, 0) << "ERROR: zonegroup " << local_zonegroup->id + << " does not contain zone id " << zone_id << dendl; + r = -ENOENT; + } + + local_zonegroup = std::nullopt; + return r; +} + } // namespace rgw +static inline int conf_to_uint64(const JSONFormattable& config, const string& key, uint64_t *pval) +{ + string sval; + if (config.find(key, &sval)) { + string err; + uint64_t val = strict_strtoll(sval.c_str(), 10, &err); + if (!err.empty()) { + return -EINVAL; + } + *pval = val; + } + return 0; +} + +int RGWZoneGroupPlacementTier::update_params(const JSONFormattable& config) +{ + int r = -1; + + if (config.exists("retain_head_object")) { + string s = config["retain_head_object"]; + if (s == "true") { + retain_head_object = true; + } else { + retain_head_object = false; + } + } + if (config.exists("allow_read_through")) { + string s = config["allow_read_through"]; + if (s == "true") { + allow_read_through = true; + } else { + allow_read_through = false; + } + } + if (config.exists("read_through_restore_days")) { + r = conf_to_uint64(config, "read_through_restore_days", &read_through_restore_days); + if (r < 0) { + read_through_restore_days = DEFAULT_READ_THROUGH_RESTORE_DAYS; + } + } + + if (is_tier_type_s3()) { + r = t.s3.update_params(config); + } + + if (config.exists("restore_storage_class")) { + restore_storage_class = config["restore_storage_class"]; + } + + if (is_tier_type_s3_glacier()) { + r = s3_glacier.update_params(config); + } + return r; +} + +int RGWZoneGroupPlacementTier::clear_params(const JSONFormattable& config) +{ + if (config.exists("retain_head_object")) { + retain_head_object = false; + } + if (config.exists("allow_read_through")) { + allow_read_through = false; + } + if (config.exists("read_through_restore_days")) { + read_through_restore_days = DEFAULT_READ_THROUGH_RESTORE_DAYS; + } + + if (is_tier_type_s3()) { + t.s3.clear_params(config); + } + + if (config.exists("restore_storage_class")) { + restore_storage_class = RGW_STORAGE_CLASS_STANDARD; + } + + if (is_tier_type_s3_glacier()) { + s3_glacier.clear_params(config); + } + + return 0; +} + +int RGWZoneGroupPlacementTierS3::update_params(const JSONFormattable& config) +{ + int r = -1; + + if (config.exists("endpoint")) { + endpoint = config["endpoint"]; + } + if (config.exists("target_path")) { + target_path = config["target_path"]; + } + if (config.exists("region")) { + region = config["region"]; + } + if (config.exists("host_style")) { + string s; + s = config["host_style"]; + if (s != "virtual") { + host_style = PathStyle; + } else { + host_style = VirtualStyle; + } + } + if (config.exists("target_storage_class")) { + target_storage_class = config["target_storage_class"]; + } + if (config.exists("access_key")) { + key.id = config["access_key"]; + } + if (config.exists("secret")) { + key.key = config["secret"]; + } + if (config.exists("multipart_sync_threshold")) { + r = conf_to_uint64(config, "multipart_sync_threshold", &multipart_sync_threshold); + if (r < 0) { + multipart_sync_threshold = DEFAULT_MULTIPART_SYNC_PART_SIZE; + } + } + + if (config.exists("multipart_min_part_size")) { + r = conf_to_uint64(config, "multipart_min_part_size", &multipart_min_part_size); + if (r < 0) { + multipart_min_part_size = DEFAULT_MULTIPART_SYNC_PART_SIZE; + } + } + + if (config.exists("acls")) { + const JSONFormattable& cc = config["acls"]; + if (cc.is_array()) { + for (auto& c : cc.array()) { + RGWTierACLMapping m; + m.init(c); + if (!m.source_id.empty()) { + acl_mappings[m.source_id] = m; + } + } + } else { + RGWTierACLMapping m; + m.init(cc); + if (!m.source_id.empty()) { + acl_mappings[m.source_id] = m; + } + } + } + return 0; +} + +int RGWZoneGroupPlacementTierS3::clear_params(const JSONFormattable& config) +{ + if (config.exists("endpoint")) { + endpoint.clear(); + } + if (config.exists("target_path")) { + target_path.clear(); + } + if (config.exists("region")) { + region.clear(); + } + if (config.exists("host_style")) { + /* default */ + host_style = PathStyle; + } + if (config.exists("target_storage_class")) { + target_storage_class.clear(); + } + if (config.exists("access_key")) { + key.id.clear(); + } + if (config.exists("secret")) { + key.key.clear(); + } + if (config.exists("multipart_sync_threshold")) { + multipart_sync_threshold = DEFAULT_MULTIPART_SYNC_PART_SIZE; + } + if (config.exists("multipart_min_part_size")) { + multipart_min_part_size = DEFAULT_MULTIPART_SYNC_PART_SIZE; + } + if (config.exists("acls")) { + const JSONFormattable& cc = config["acls"]; + if (cc.is_array()) { + for (auto& c : cc.array()) { + RGWTierACLMapping m; + m.init(c); + acl_mappings.erase(m.source_id); + } + } else { + RGWTierACLMapping m; + m.init(cc); + acl_mappings.erase(m.source_id); + } + } + return 0; +} + +int RGWZoneGroupTierS3Glacier::update_params(const JSONFormattable& config) +{ + int r = -1; + + if (config.exists("glacier_restore_days")) { + r = conf_to_uint64(config, "glacier_restore_days", &glacier_restore_days); + if (r < 0) { + glacier_restore_days = DEFAULT_GLACIER_RESTORE_DAYS; + } + } + if (config.exists("glacier_restore_tier_type")) { + string s; + s = config["glacier_restore_tier_type"]; + if (s != "Expedited") { + glacier_restore_tier_type = Standard; + } else { + glacier_restore_tier_type = Expedited; + } + } + return 0; +} + +int RGWZoneGroupTierS3Glacier::clear_params(const JSONFormattable& config) +{ + if (config.exists("glacier_restore_days")) { + glacier_restore_days = DEFAULT_GLACIER_RESTORE_DAYS; + } + if (config.exists("glacier_restore_tier_type")) { + /* default */ + glacier_restore_tier_type = Standard; + } + return 0; +} + +void rgw_meta_sync_info::generate_test_instances(list& o) +{ + auto info = new rgw_meta_sync_info; + info->state = rgw_meta_sync_info::StateBuildingFullSyncMaps; + info->period = "periodid"; + info->realm_epoch = 5; + o.push_back(info); + o.push_back(new rgw_meta_sync_info); +} + +void rgw_meta_sync_marker::generate_test_instances(list& o) +{ + auto marker = new rgw_meta_sync_marker; + marker->state = rgw_meta_sync_marker::IncrementalSync; + marker->marker = "01234"; + marker->realm_epoch = 5; + o.push_back(marker); + o.push_back(new rgw_meta_sync_marker); +} + +void rgw_meta_sync_status::generate_test_instances(list& o) +{ + o.push_back(new rgw_meta_sync_status); +} + +void RGWZoneParams::generate_test_instances(list &o) +{ + o.push_back(new RGWZoneParams); + o.push_back(new RGWZoneParams); +} + +void RGWPeriodLatestEpochInfo::generate_test_instances(list &o) +{ + RGWPeriodLatestEpochInfo *z = new RGWPeriodLatestEpochInfo; + o.push_back(z); + o.push_back(new RGWPeriodLatestEpochInfo); +} + +void RGWZoneGroup::generate_test_instances(list& o) +{ + RGWZoneGroup *r = new RGWZoneGroup; + o.push_back(r); + o.push_back(new RGWZoneGroup); +} + +void RGWPeriodLatestEpochInfo::dump(Formatter *f) const { + encode_json("latest_epoch", epoch, f); +} + +void RGWPeriodLatestEpochInfo::decode_json(JSONObj *obj) { + JSONDecoder::decode_json("latest_epoch", epoch, obj); +} + +void RGWNameToId::dump(Formatter *f) const { + encode_json("obj_id", obj_id, f); +} + +void RGWNameToId::decode_json(JSONObj *obj) { + JSONDecoder::decode_json("obj_id", obj_id, obj); +} + +void RGWNameToId::generate_test_instances(list& o) { + RGWNameToId *n = new RGWNameToId; + n->obj_id = "id"; + o.push_back(n); + o.push_back(new RGWNameToId); +} + diff --git a/src/rgw/driver/rados/rgw_zone.h b/src/rgw/rgw_zone.h similarity index 99% rename from src/rgw/driver/rados/rgw_zone.h rename to src/rgw/rgw_zone.h index ff344a173d9..418214c32cb 100644 --- a/src/rgw/driver/rados/rgw_zone.h +++ b/src/rgw/rgw_zone.h @@ -439,6 +439,7 @@ WRITE_CLASS_ENCODER(RGWPeriodConfig) class RGWRealm; class RGWPeriod; +namespace rgw {class SiteConfig;} class RGWRealm { @@ -752,7 +753,7 @@ int commit_period(const DoutPrefixProvider* dpp, optional_yield y, RGWRealm& realm, sal::RealmWriter& realm_writer, const RGWPeriod& current_period, RGWPeriod& info, std::ostream& error_stream, - bool force_if_stale); + bool force_if_stale, const rgw::SiteConfig& site); /// Look up a zonegroup by its id. If no id is given, look it up by name. diff --git a/src/rgw/services/svc_mdlog.cc b/src/rgw/services/svc_mdlog.cc index b8f86c61a01..89a5ec44fb8 100644 --- a/src/rgw/services/svc_mdlog.cc +++ b/src/rgw/services/svc_mdlog.cc @@ -12,7 +12,7 @@ #include "rgw_coroutine.h" #include "rgw_cr_rados.h" -#include "driver/rados/rgw_zone.h" // FIXME: subclass dependency +#include "rgw/rgw_zone.h" #include "common/errno.h" diff --git a/src/rgw/services/svc_zone.cc b/src/rgw/services/svc_zone.cc index 6cd8c0a28af..07654e832d8 100644 --- a/src/rgw/services/svc_zone.cc +++ b/src/rgw/services/svc_zone.cc @@ -427,11 +427,6 @@ const RGWZone& RGWSI_Zone::get_zone() const return *zone_public_config; } -const RGWZoneGroup& RGWSI_Zone::get_zonegroup() const -{ - return *zonegroup; -} - int RGWSI_Zone::get_zonegroup(const string& id, RGWZoneGroup& zg) const { int ret = 0; @@ -516,11 +511,6 @@ bool RGWSI_Zone::need_to_sync() const current_period->get_id().empty()); } -bool RGWSI_Zone::need_to_log_data() const -{ - return (zone_public_config->log_data && sync_module_exports_data()); -} - bool RGWSI_Zone::is_meta_master() const { if (!zonegroup->is_master_zonegroup()) { diff --git a/src/rgw/services/svc_zone.h b/src/rgw/services/svc_zone.h index 7256aae3728..de56cde6e5f 100644 --- a/src/rgw/services/svc_zone.h +++ b/src/rgw/services/svc_zone.h @@ -75,7 +75,7 @@ public: const RGWZoneParams& get_zone_params() const; const RGWPeriod& get_current_period() const; const RGWRealm& get_realm() const; - const RGWZoneGroup& get_zonegroup() const; + const RGWZoneGroup& get_zonegroup() const { return *zonegroup; }; int get_zonegroup(const std::string& id, RGWZoneGroup& zonegroup) const; const RGWZone& get_zone() const; @@ -134,7 +134,7 @@ public: bool is_meta_master() const; bool need_to_sync() const; - bool need_to_log_data() const; + bool need_to_log_data() const { return (zone_public_config->log_data && sync_module_exports_data()); }; bool need_to_log_metadata() const; bool can_reshard() const; bool is_syncing_bucket_meta() const; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index a94826f7ad7..7a21f2b9817 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -614,7 +614,7 @@ if(WITH_RBD) add_dependencies(tests unittest_librbd rbd-mirror) endif(WITH_RBD_MIRROR) endif(WITH_RBD) -if(WITH_RADOSGW) +if(WITH_RADOSGW AND WITH_RADOSGW_RADOS) add_dependencies(tests radosgw radosgw-admin) endif() #add dependency from fio just to ensure the plugin build isn't failing diff --git a/src/test/rgw/CMakeLists.txt b/src/test/rgw/CMakeLists.txt index 56050317314..f9305c5afc6 100644 --- a/src/test/rgw/CMakeLists.txt +++ b/src/test/rgw/CMakeLists.txt @@ -143,6 +143,7 @@ add_executable(unittest_rgw_ratelimit test_rgw_ratelimit.cc $) target_include_directories(ceph_test_rgw_gc_log SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw") target_link_libraries(ceph_test_rgw_gc_log ${rgw_libs} radostest-cxx) install(TARGETS ceph_test_rgw_gc_log DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() add_executable(unittest_rgw_shard_io test_rgw_shard_io.cc) add_ceph_unittest(unittest_rgw_shard_io) @@ -325,6 +331,7 @@ target_link_libraries(unittest_rgw_shard_io ${rgw_libs} unit-main ${UNITTEST_LIB add_ceph_test(test-ceph-diff-sorted.sh ${CMAKE_CURRENT_SOURCE_DIR}/test-ceph-diff-sorted.sh) +if(WITH_RADOSGW_RADOS) # unittest_log_backing add_executable(unittest_log_backing test_log_backing.cc) target_include_directories(unittest_log_backing @@ -335,6 +342,7 @@ target_link_libraries(unittest_log_backing neoradostest-support ${UNITTEST_LIBS} ${rgw_libs}) +endif() add_executable(unittest_rgw_lua test_rgw_lua.cc) add_ceph_unittest(unittest_rgw_lua) @@ -342,6 +350,7 @@ target_include_directories(unittest_rgw_lua SYSTEM PRIVATE "${CMAKE_SOURCE_DIR}/src/rgw") target_link_libraries(unittest_rgw_lua unit-main ${rgw_libs}) +if(WITH_RADOSGW_RADOS) add_executable(radosgw-cr-test rgw_cr_test.cc) target_link_libraries(radosgw-cr-test ${rgw_libs} librados cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client @@ -351,6 +360,7 @@ target_link_libraries(radosgw-cr-test ${rgw_libs} librados OATH::OATH ${CURL_LIBRARIES} ${EXPAT_LIBRARIES} ${BLKID_LIBRARIES} GTest::GTest) +endif() if(WITH_RADOSGW_POSIX) # unittest_posix_bucket_cache @@ -376,6 +386,7 @@ target_link_libraries(unittest_rgw_posix_driver ${UNITTEST_LIBS} ${rgw_libs} ${LMDB_LIBRARIES}) endif(WITH_RADOSGW_POSIX) +if(WITH_RADOSGW_RADOS) # ceph_test_datalog add_executable(ceph_test_datalog test_datalog.cc) target_include_directories(ceph_test_datalog @@ -387,6 +398,7 @@ target_link_libraries(ceph_test_datalog ${UNITTEST_LIBS} ${rgw_libs}) install(TARGETS ceph_test_datalog DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() if(WITH_CATCH2) add_executable(unittest_rgw_hex diff --git a/src/test/rgw/rgw_cr_test.cc b/src/test/rgw/rgw_cr_test.cc index 78b6fc9413b..f75f79132eb 100644 --- a/src/test/rgw/rgw_cr_test.cc +++ b/src/test/rgw/rgw_cr_test.cc @@ -21,7 +21,7 @@ #include "rgw_cr_rados.h" #include "rgw_sal.h" #include "rgw_sal_rados.h" -#include "driver/rados/rgw_zone.h" +#include "rgw/rgw_zone.h" #include "rgw_sal_config.h" #include "gtest/gtest.h" diff --git a/src/test/rgw/test_rgw_iam_policy.cc b/src/test/rgw/test_rgw_iam_policy.cc index 8e9be5c11e5..057bcab362b 100644 --- a/src/test/rgw/test_rgw_iam_policy.cc +++ b/src/test/rgw/test_rgw_iam_policy.cc @@ -32,7 +32,7 @@ #include "rgw_op.h" #include "rgw_process_env.h" #include "rgw_sal_rados.h" -#include "driver/rados/rgw_zone.h" +#include "rgw_zone.h" #include "rgw_sal_config.h" using std::string; -- 2.39.5