]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add SiteConfig to load/create zonegroup configuration
authorCasey Bodley <cbodley@redhat.com>
Thu, 13 Oct 2022 19:09:16 +0000 (15:09 -0400)
committerCasey Bodley <cbodley@redhat.com>
Sun, 12 Mar 2023 23:05:22 +0000 (19:05 -0400)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/driver/rados/rgw_zone.cc
src/rgw/driver/rados/rgw_zone.h

index 339d337b6d440d5f4bdaf19501318c9edfbafdf4..9afd62a75ae44b8a16a6e0a304a4a58c63cd91e4 100644 (file)
@@ -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<std::string> 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)
index 2d69d5f1c7230ecf41b0ca734d764394635d42f2..140678fcdce5afc06b0e18fd6c375b5f727d76a4 100644 (file)
@@ -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<RGWRealm>& get_realm() const { return realm; }
+  /// Return the current period configuration, if a period is present.
+  const std::optional<RGWPeriod>& 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<RGWRealm> realm;
+  std::optional<RGWPeriod> period;
+  std::optional<RGWZoneGroup> local_zonegroup;
+  const RGWZoneGroup* zonegroup = nullptr;
+  const RGWZone* zone = nullptr;
+};
+
 } // namespace rgw