From: Casey Bodley Date: Thu, 13 Oct 2022 19:09:16 +0000 (-0400) Subject: rgw: add SiteConfig to load/create zonegroup configuration X-Git-Tag: v19.0.0~1552^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f887f9a8b6fadd467f05c3aea3db5288f9b90944;p=ceph.git rgw: add SiteConfig to load/create zonegroup configuration Signed-off-by: Casey Bodley --- diff --git a/src/rgw/driver/rados/rgw_zone.cc b/src/rgw/driver/rados/rgw_zone.cc index 339d337b6d44..9afd62a75ae4 100644 --- a/src/rgw/driver/rados/rgw_zone.cc +++ b/src/rgw/driver/rados/rgw_zone.cc @@ -874,6 +874,37 @@ int create_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, 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::supported.begin(), + rgw::zone_features::supported.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) @@ -1061,6 +1092,191 @@ int delete_zone(const DoutPrefixProvider* dpp, optional_yield y, return writer.remove(dpp, y); } + +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) +{ + // 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); + } 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) { + // try to load the realm's period + r = load_period_zonegroup(dpp, y, cfgstore, *realm, zone_params.id); + } else { + // fall back to a local zonegroup + r = load_local_zonegroup(dpp, y, cfgstore, zone_params.id); + } + + return r; +} + +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 { + 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) diff --git a/src/rgw/driver/rados/rgw_zone.h b/src/rgw/driver/rados/rgw_zone.h index 2d69d5f1c723..140678fcdce5 100644 --- a/src/rgw/driver/rados/rgw_zone.h +++ b/src/rgw/driver/rados/rgw_zone.h @@ -940,4 +940,42 @@ int delete_zone(const DoutPrefixProvider* dpp, optional_yield y, sal::ConfigStore* cfgstore, const RGWZoneParams& info, sal::ZoneWriter& writer); + +/// Global state about the site configuration. Initialized once during +/// startup and may be reinitialized by RGWRealmReloader, but is otherwise +/// immutable at runtime. +class SiteConfig { + public: + /// Return the local zone params. + const RGWZoneParams& get_zone_params() const { return zone_params; } + /// Return the current realm configuration, if a realm is present. + const std::optional& get_realm() const { return realm; } + /// Return the current period configuration, if a period is present. + const std::optional& get_period() const { return period; } + /// Return the zonegroup configuration. + const RGWZoneGroup& get_zonegroup() const { return *zonegroup; } + /// Return the public zone configuration. + const RGWZone& get_zone() const { return *zone; } + + /// Load or reload the multisite configuration from storage. This is not + /// thread-safe, so requires careful coordination with the RGWRealmReloader. + int load(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore); + + private: + int load_period_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, const RGWRealm& realm, + const rgw_zone_id& zone_id); + int load_local_zonegroup(const DoutPrefixProvider* dpp, optional_yield y, + sal::ConfigStore* cfgstore, + const rgw_zone_id& zone_id); + + RGWZoneParams zone_params; + std::optional realm; + std::optional period; + std::optional local_zonegroup; + const RGWZoneGroup* zonegroup = nullptr; + const RGWZone* zone = nullptr; +}; + } // namespace rgw