]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: svc: initial work on zone_svc
authorYehuda Sadeh <yehuda@redhat.com>
Fri, 10 Aug 2018 21:36:48 +0000 (14:36 -0700)
committerYehuda Sadeh <yehuda@redhat.com>
Thu, 8 Nov 2018 17:18:09 +0000 (09:18 -0800)
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
src/rgw/CMakeLists.txt
src/rgw/rgw_rados.cc
src/rgw/rgw_rados.h
src/rgw/rgw_service.h
src/rgw/rgw_zone.cc [new file with mode: 0644]
src/rgw/rgw_zone.h [new file with mode: 0644]
src/rgw/services/svc_rados.h
src/rgw/services/svc_zone.cc [new file with mode: 0644]
src/rgw/services/svc_zone.h [new file with mode: 0644]

index fa3a4d3c5a1c13cf5c0e233a1f46fa89e3fe08c9..0e376bd94c0aeca0766f7b9e0949e8f4ef95654d 100644 (file)
@@ -40,6 +40,7 @@ endfunction()
 
 set(librgw_common_srcs
   services/svc_rados.cc
+  services/svc_zone.cc
   rgw_service.cc
   rgw_acl.cc
   rgw_acl_s3.cc
index 780863afdabefcb63dd8e8886736f3ca1ae2bea6..42d33420442726994efa05f3b69782276cf0613d 100644 (file)
@@ -236,1851 +236,6 @@ void RGWObjectCtxImpl<rgw_raw_obj, RGWRawObjState>::invalidate(const rgw_raw_obj
   objs_state.erase(iter);
 }
 
-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);
-  }
-}
-
-rgw_pool RGWZoneGroup::get_pool(CephContext *cct_)
-{
-  if (cct_->_conf->rgw_zonegroup_root_pool.empty()) {
-    return rgw_pool(RGW_DEFAULT_ZONEGROUP_ROOT_POOL);
-  }
-
-  return rgw_pool(cct_->_conf->rgw_zonegroup_root_pool);
-}
-
-int RGWZoneGroup::create_default(bool old_format)
-{
-  name = default_zonegroup_name;
-  api_name = default_zonegroup_name;
-  is_master = true;
-
-  RGWZoneGroupPlacementTarget placement_target;
-  placement_target.name = "default-placement";
-  placement_targets[placement_target.name] = placement_target;
-  default_placement = "default-placement";
-
-  RGWZoneParams zone_params(default_zone_name);
-
-  int r = zone_params.init(cct, store, false);
-  if (r < 0) {
-    ldout(cct, 0) << "create_default: error initializing zone params: " << cpp_strerror(-r) << dendl;
-    return r;
-  }
-
-  r = zone_params.create_default();
-  if (r < 0 && r != -EEXIST) {
-    ldout(cct, 0) << "create_default: error in create_default  zone params: " << cpp_strerror(-r) << dendl;
-    return r;
-  } else if (r == -EEXIST) {
-    ldout(cct, 10) << "zone_params::create_default() returned -EEXIST, we raced with another default zone_params creation" << dendl;
-    zone_params.clear_id();
-    r = zone_params.init(cct, store);
-    if (r < 0) {
-      ldout(cct, 0) << "create_default: error in init existing zone params: " << cpp_strerror(-r) << dendl;
-      return r;
-    }
-    ldout(cct, 20) << "zone_params::create_default() " << zone_params.get_name() << " id " << zone_params.get_id()
-                  << dendl;
-  }
-  
-  RGWZone& default_zone = zones[zone_params.get_id()];
-  default_zone.name = zone_params.get_name();
-  default_zone.id = zone_params.get_id();
-  master_zone = default_zone.id;
-  
-  r = create();
-  if (r < 0 && r != -EEXIST) {
-    ldout(cct, 0) << "error storing zone group info: " << cpp_strerror(-r) << dendl;
-    return r;
-  }
-
-  if (r == -EEXIST) {
-    ldout(cct, 10) << "create_default() returned -EEXIST, we raced with another zonegroup creation" << dendl;
-    id.clear();
-    r = init(cct, store);
-    if (r < 0) {
-      return r;
-    }
-  }
-
-  if (old_format) {
-    name = id;
-  }
-
-  post_process_params();
-
-  return 0;
-}
-
-const string RGWZoneGroup::get_default_oid(bool old_region_format)
-{
-  if (old_region_format) {
-    if (cct->_conf->rgw_default_region_info_oid.empty()) {
-      return default_region_info_oid;
-    }
-    return cct->_conf->rgw_default_region_info_oid;
-  }
-
-  string default_oid = cct->_conf->rgw_default_zonegroup_info_oid;
-
-  if (cct->_conf->rgw_default_zonegroup_info_oid.empty()) {
-    default_oid = default_zone_group_info_oid;
-  }
-
-  default_oid += "." + realm_id;
-
-  return default_oid;
-}
-
-const string& RGWZoneGroup::get_info_oid_prefix(bool old_region_format)
-{
-  if (old_region_format) {
-    return region_info_oid_prefix;
-  }
-  return zone_group_info_oid_prefix;
-}
-
-const string& RGWZoneGroup::get_names_oid_prefix()
-{
-  return zonegroup_names_oid_prefix;
-}
-
-const string& RGWZoneGroup::get_predefined_name(CephContext *cct) {
-  return cct->_conf->rgw_zonegroup;
-}
-
-int RGWZoneGroup::equals(const string& other_zonegroup) const
-{
-  if (is_master && other_zonegroup.empty())
-    return true;
-
-  return (id  == other_zonegroup);
-}
-
-int RGWZoneGroup::add_zone(const RGWZoneParams& zone_params, bool *is_master, bool *read_only,
-                           const list<string>& endpoints, const string *ptier_type,
-                           bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm,
-                           string *predirect_zone)
-{
-  auto& zone_id = zone_params.get_id();
-  auto& zone_name = zone_params.get_name();
-
-  // check for duplicate zone name on insert
-  if (!zones.count(zone_id)) {
-    for (const auto& zone : zones) {
-      if (zone.second.name == zone_name) {
-        ldout(cct, 0) << "ERROR: found existing zone name " << zone_name
-            << " (" << zone.first << ") in zonegroup " << get_name() << dendl;
-        return -EEXIST;
-      }
-    }
-  }
-
-  if (is_master) {
-    if (*is_master) {
-      if (!master_zone.empty() && master_zone != zone_id) {
-        ldout(cct, 0) << "NOTICE: overriding master zone: " << master_zone << dendl;
-      }
-      master_zone = zone_id;
-    } else if (master_zone == zone_id) {
-      master_zone.clear();
-    }
-  }
-
-  RGWZone& zone = zones[zone_id];
-  zone.name = zone_name;
-  zone.id = zone_id;
-  if (!endpoints.empty()) {
-    zone.endpoints = endpoints;
-  }
-  if (read_only) {
-    zone.read_only = *read_only;
-  }
-  if (ptier_type) {
-    zone.tier_type = *ptier_type;
-    if (!store->get_sync_modules_manager()->get_module(*ptier_type, nullptr)) {
-      ldout(cct, 0) << "ERROR: could not found sync module: " << *ptier_type 
-                    << ",  valid sync modules: " 
-                    << store->get_sync_modules_manager()->get_registered_module_names()
-                    << dendl;
-      return -ENOENT;
-    }
-  }
-
-  if (psync_from_all) {
-    zone.sync_from_all = *psync_from_all;
-  }
-
-  if (predirect_zone) {
-    zone.redirect_zone = *predirect_zone;
-  }
-
-  for (auto add : sync_from) {
-    zone.sync_from.insert(add);
-  }
-
-  for (auto rm : sync_from_rm) {
-    zone.sync_from.erase(rm);
-  }
-
-  post_process_params();
-
-  return update();
-}
-
-
-int RGWZoneGroup::rename_zone(const RGWZoneParams& zone_params)
-{ 
-  RGWZone& zone = zones[zone_params.get_id()];
-  zone.name = zone_params.get_name();
-  
-  return update();
-}
-
-void RGWZoneGroup::post_process_params()
-{
-  bool log_data = zones.size() > 1;
-
-  if (master_zone.empty()) {
-    map<string, RGWZone>::iterator iter = zones.begin();
-    if (iter != zones.end()) {
-      master_zone = iter->first;
-    }
-  }
-  
-  for (map<string, RGWZone>::iterator iter = zones.begin(); iter != zones.end(); ++iter) {
-    RGWZone& zone = iter->second;
-    zone.log_data = log_data;
-
-    RGWZoneParams zone_params(zone.id, zone.name);
-    int ret = zone_params.init(cct, store);
-    if (ret < 0) {
-      ldout(cct, 0) << "WARNING: could not read zone params for zone id=" << zone.id << " name=" << zone.name << dendl;
-      continue;
-    }
-
-    for (map<string, RGWZonePlacementInfo>::iterator iter = zone_params.placement_pools.begin(); 
-         iter != zone_params.placement_pools.end(); ++iter) {
-      const string& placement_name = iter->first;
-      if (placement_targets.find(placement_name) == placement_targets.end()) {
-        RGWZoneGroupPlacementTarget placement_target;
-        placement_target.name = placement_name;
-        placement_targets[placement_name] = placement_target;
-      }
-    }
-  }
-
-  if (default_placement.empty() && !placement_targets.empty()) {
-    default_placement = placement_targets.begin()->first;
-  }
-}
-
-int RGWZoneGroup::remove_zone(const std::string& zone_id)
-{
-  map<string, RGWZone>::iterator iter = zones.find(zone_id);
-  if (iter == zones.end()) {
-    ldout(cct, 0) << "zone id " << zone_id << " is not a part of zonegroup "
-        << name << dendl;
-    return -ENOENT;
-  }
-
-  zones.erase(iter);
-
-  post_process_params();
-
-  return update();
-}
-
-int RGWZoneGroup::read_default_id(string& default_id, bool old_format)
-{
-  if (realm_id.empty()) {
-    /* try using default realm */
-    RGWRealm realm;
-    int ret = realm.init(cct, store);
-    // no default realm exist
-    if (ret < 0) {
-      return read_id(default_zonegroup_name, default_id);
-    }
-    realm_id = realm.get_id();
-  }
-
-  return RGWSystemMetaObj::read_default_id(default_id, old_format);
-}
-
-int RGWZoneGroup::set_as_default(bool exclusive)
-{
-  if (realm_id.empty()) {
-    /* try using default realm */
-    RGWRealm realm;
-    int ret = realm.init(cct, store);
-    if (ret < 0) {
-      ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
-      return -EINVAL;
-    }
-    realm_id = realm.get_id();
-  }
-
-  return RGWSystemMetaObj::set_as_default(exclusive);
-}
-
-int RGWSystemMetaObj::init(CephContext *_cct, RGWRados *_store, bool setup_obj, bool old_format)
-{
-  cct = _cct;
-  store = _store;
-
-  if (!setup_obj)
-    return 0;
-
-  if (old_format && id.empty()) {
-    id = name;
-  }
-
-  if (id.empty()) {
-    int r;
-    if (name.empty()) {
-      name = get_predefined_name(cct);
-    }
-    if (name.empty()) {
-      r = use_default(old_format);
-      if (r < 0) {
-       return r;
-      }
-    } else if (!old_format) {
-      r = read_id(name, id);
-      if (r < 0) {
-        if (r != -ENOENT) {
-          ldout(cct, 0) << "error in read_id for object name: " << name << " : " << cpp_strerror(-r) << dendl;
-        }
-        return r;
-      }
-    }
-  }
-
-  return read_info(id, old_format);
-}
-
-int RGWSystemMetaObj::read_default(RGWDefaultSystemMetaObjInfo& default_info, const string& oid)
-{
-  using ceph::decode;
-  auto pool = get_pool(cct);
-  bufferlist bl;
-  RGWObjectCtx obj_ctx(store);
-  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
-  if (ret < 0)
-    return ret;
-
-  try {
-    auto iter = bl.cbegin();
-    decode(default_info, iter);
-  } catch (buffer::error& err) {
-    ldout(cct, 0) << "error decoding data from " << pool << ":" << oid << dendl;
-    return -EIO;
-  }
-
-  return 0;
-}
-
-int RGWSystemMetaObj::read_default_id(string& default_id, bool old_format)
-{
-  RGWDefaultSystemMetaObjInfo default_info;
-
-  int ret = read_default(default_info, get_default_oid(old_format));
-  if (ret < 0) {
-    return ret;
-  }
-
-  default_id = default_info.default_id;
-
-  return 0;
-}
-
-int RGWSystemMetaObj::use_default(bool old_format)
-{
-  return read_default_id(id, old_format);
-}
-
-int RGWSystemMetaObj::set_as_default(bool exclusive)
-{
-  using ceph::encode;
-  string oid  = get_default_oid();
-
-  rgw_pool pool(get_pool(cct));
-  bufferlist bl;
-
-  RGWDefaultSystemMetaObjInfo default_info;
-  default_info.default_id = id;
-
-  encode(default_info, bl);
-
-  int ret = rgw_put_system_obj(store, pool, oid, bl,
-                               exclusive, NULL, real_time(), NULL);
-  if (ret < 0)
-    return ret;
-
-  return 0;
-}
-
-int RGWSystemMetaObj::read_id(const string& obj_name, string& object_id)
-{
-  using ceph::decode;
-  rgw_pool pool(get_pool(cct));
-  bufferlist bl;
-
-  string oid = get_names_oid_prefix() + obj_name;
-
-  RGWObjectCtx obj_ctx(store);
-  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
-  if (ret < 0) {
-    return ret;
-  }
-
-  RGWNameToId nameToId;
-  try {
-    auto iter = bl.cbegin();
-    decode(nameToId, iter);
-  } catch (buffer::error& err) {
-    ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
-    return -EIO;
-  }
-  object_id = nameToId.obj_id;
-  return 0;
-}
-
-int RGWSystemMetaObj::delete_obj(bool old_format)
-{
-  rgw_pool pool(get_pool(cct));
-
-  /* check to see if obj is the default */
-  RGWDefaultSystemMetaObjInfo default_info;
-  int ret = read_default(default_info, get_default_oid(old_format));
-  if (ret < 0 && ret != -ENOENT)
-    return ret;
-  if (default_info.default_id == id || (old_format && default_info.default_id == name)) {
-    string oid = get_default_oid(old_format);
-    rgw_raw_obj default_named_obj(pool, oid);
-    ret = store->delete_system_obj(default_named_obj);
-    if (ret < 0) {
-      ldout(cct, 0) << "Error delete default obj name  " << name << ": " << cpp_strerror(-ret) << dendl;
-      return ret;
-    }
-  }
-  if (!old_format) {
-    string oid  = get_names_oid_prefix() + name;
-    rgw_raw_obj object_name(pool, oid);
-    ret = store->delete_system_obj(object_name);
-    if (ret < 0) {
-      ldout(cct, 0) << "Error delete obj name  " << name << ": " << cpp_strerror(-ret) << dendl;
-      return ret;
-    }
-  }
-
-  string oid = get_info_oid_prefix(old_format);
-  if (old_format) {
-    oid += name;
-  } else {
-    oid += id;
-  }
-
-  rgw_raw_obj object_id(pool, oid);
-  ret = store->delete_system_obj(object_id);
-  if (ret < 0) {
-    ldout(cct, 0) << "Error delete object id " << id << ": " << cpp_strerror(-ret) << dendl;
-  }
-
-  return ret;
-}
-
-int RGWSystemMetaObj::store_name(bool exclusive)
-{
-  rgw_pool pool(get_pool(cct));
-  string oid = get_names_oid_prefix() + name;
-
-  RGWNameToId nameToId;
-  nameToId.obj_id = id;
-
-  bufferlist bl;
-  using ceph::encode;
-  encode(nameToId, bl);
-  return rgw_put_system_obj(store, pool, oid, bl, exclusive, NULL, real_time(), NULL);
-}
-
-int RGWSystemMetaObj::rename(const string& new_name)
-{
-  string new_id;
-  int ret = read_id(new_name, new_id);
-  if (!ret) {
-    return -EEXIST;
-  }
-  if (ret < 0 && ret != -ENOENT) {
-    ldout(cct, 0) << "Error read_id " << new_name << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-  string old_name = name;
-  name = new_name;
-  ret = update();
-  if (ret < 0) {
-    ldout(cct, 0) << "Error storing new obj info " << new_name << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-  ret = store_name(true);
-  if (ret < 0) {
-    ldout(cct, 0) << "Error storing new name " << new_name << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-  /* delete old name */
-  rgw_pool pool(get_pool(cct));
-  string oid = get_names_oid_prefix() + old_name;
-  rgw_raw_obj old_name_obj(pool, oid);
-  ret = store->delete_system_obj(old_name_obj);
-  if (ret < 0) {
-    ldout(cct, 0) << "Error delete old obj name  " << old_name << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  return ret;
-}
-
-int RGWSystemMetaObj::read_info(const string& obj_id, bool old_format)
-{
-  rgw_pool pool(get_pool(cct));
-
-  bufferlist bl;
-
-  string oid = get_info_oid_prefix(old_format) + obj_id;
-
-  RGWObjectCtx obj_ctx(store);
-  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
-  if (ret < 0) {
-    ldout(cct, 0) << "failed reading obj info from " << pool << ":" << oid << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-  using ceph::decode;
-
-  try {
-    auto iter = bl.cbegin();
-    decode(*this, iter);
-  } catch (buffer::error& err) {
-    ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
-    return -EIO;
-  }
-
-  return 0;
-}
-
-int RGWSystemMetaObj::read()
-{
-  int ret = read_id(name, id);
-  if (ret < 0) {
-    return ret;
-  }
-
-  return read_info(id);
-}
-
-int RGWSystemMetaObj::create(bool exclusive)
-{
-  int ret;
-  
-  /* check to see the name is not used */
-  ret = read_id(name, id);
-  if (exclusive && ret == 0) {
-    ldout(cct, 10) << "ERROR: name " << name << " already in use for obj id " << id << dendl;
-    return -EEXIST;
-  } else if ( ret < 0 && ret != -ENOENT) {
-    ldout(cct, 0) << "failed reading obj id  " << id << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  if (id.empty()) {
-    /* create unique id */
-    uuid_d new_uuid;
-    char uuid_str[37];
-    new_uuid.generate_random();
-    new_uuid.print(uuid_str);
-    id = uuid_str;
-  }
-
-  ret = store_info(exclusive);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR:  storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  return store_name(exclusive);
-}
-
-int RGWSystemMetaObj::store_info(bool exclusive)
-{
-  rgw_pool pool(get_pool(cct));
-
-  string oid = get_info_oid_prefix() + id;
-
-  bufferlist bl;
-  using ceph::encode;
-  encode(*this, bl);
-  return rgw_put_system_obj(store, pool, oid, bl, exclusive, NULL, real_time(), NULL);
-}
-
-int RGWSystemMetaObj::write(bool exclusive)
-{
-  int ret = store_info(exclusive);
-  if (ret < 0) {
-    ldout(cct, 20) << __func__ << "(): store_info() returned ret=" << ret << dendl;
-    return ret;
-  }
-  ret = store_name(exclusive);
-  if (ret < 0) {
-    ldout(cct, 20) << __func__ << "(): store_name() returned ret=" << ret << dendl;
-    return ret;
-  }
-  return 0;
-}
-
-
-const string& RGWRealm::get_predefined_name(CephContext *cct) {
-  return cct->_conf->rgw_realm;
-}
-
-int RGWRealm::create(bool exclusive)
-{
-  int ret = RGWSystemMetaObj::create(exclusive);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR creating new realm object " << name << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-  // create the control object for watch/notify
-  ret = create_control(exclusive);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR creating control for new realm " << name << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-  RGWPeriod period;
-  if (current_period.empty()) {
-    /* create new period for the realm */
-    ret = period.init(cct, store, id, name, false);
-    if (ret < 0 ) {
-      return ret;
-    }
-    ret = period.create(true);
-    if (ret < 0) {
-      ldout(cct, 0) << "ERROR: creating new period for realm " << name << ": " << cpp_strerror(-ret) << dendl;
-      return ret;
-    }
-  } else {
-    period = RGWPeriod(current_period, 0);
-    int ret = period.init(cct, store, id, name);
-    if (ret < 0) {
-      ldout(cct, 0) << "ERROR: failed to init period " << current_period << dendl;
-      return ret;
-    }
-  }
-  ret = set_current_period(period);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR: failed set current period " << current_period << dendl;
-    return ret;
-  }
-  // try to set as default. may race with another create, so pass exclusive=true
-  // so we don't override an existing default
-  ret = set_as_default(true);
-  if (ret < 0 && ret != -EEXIST) {
-    ldout(cct, 0) << "WARNING: failed to set realm as default realm, ret=" << ret << dendl;
-  }
-
-  return 0;
-}
-
-int RGWRealm::delete_obj()
-{
-  int ret = RGWSystemMetaObj::delete_obj();
-  if (ret < 0) {
-    return ret;
-  }
-  return delete_control();
-}
-
-int RGWRealm::create_control(bool exclusive)
-{
-  auto pool = rgw_pool{get_pool(cct)};
-  auto oid = get_control_oid();
-  bufferlist bl;
-  return rgw_put_system_obj(store, pool, oid, bl, exclusive,
-                            nullptr, real_time(), nullptr);
-}
-
-int RGWRealm::delete_control()
-{
-  auto pool = rgw_pool{get_pool(cct)};
-  auto obj = rgw_raw_obj{pool, get_control_oid()};
-  return store->delete_system_obj(obj);
-}
-
-rgw_pool RGWRealm::get_pool(CephContext *cct)
-{
-  if (cct->_conf->rgw_realm_root_pool.empty()) {
-    return rgw_pool(RGW_DEFAULT_REALM_ROOT_POOL);
-  }
-  return rgw_pool(cct->_conf->rgw_realm_root_pool);
-}
-
-const string RGWRealm::get_default_oid(bool old_format)
-{
-  if (cct->_conf->rgw_default_realm_info_oid.empty()) {
-    return default_realm_info_oid;
-  }
-  return cct->_conf->rgw_default_realm_info_oid;
-}
-
-const string& RGWRealm::get_names_oid_prefix()
-{
-  return realm_names_oid_prefix;
-}
-
-const string& RGWRealm::get_info_oid_prefix(bool old_format)
-{
-  return realm_info_oid_prefix;
-}
-
-int RGWRealm::set_current_period(RGWPeriod& period)
-{
-  // update realm epoch to match the period's
-  if (epoch > period.get_realm_epoch()) {
-    ldout(cct, 0) << "ERROR: set_current_period with old realm epoch "
-        << period.get_realm_epoch() << ", current epoch=" << epoch << dendl;
-    return -EINVAL;
-  }
-  if (epoch == period.get_realm_epoch() && current_period != period.get_id()) {
-    ldout(cct, 0) << "ERROR: set_current_period with same realm epoch "
-        << period.get_realm_epoch() << ", but different period id "
-        << period.get_id() << " != " << current_period << dendl;
-    return -EINVAL;
-  }
-
-  epoch = period.get_realm_epoch();
-  current_period = period.get_id();
-
-  int ret = update();
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR: period update: " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  ret = period.reflect();
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR: period.reflect(): " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  return 0;
-}
-
-string RGWRealm::get_control_oid()
-{
-  return get_info_oid_prefix() + id + ".control";
-}
-
-int RGWRealm::notify_zone(bufferlist& bl)
-{
-  // open a context on the realm's pool
-  rgw_pool pool{get_pool(cct)};
-  librados::IoCtx ctx;
-  int r = rgw_init_ioctx(store->get_rados_handle(), pool, ctx);
-  if (r < 0) {
-    ldout(cct, 0) << "Failed to open pool " << pool << dendl;
-    return r;
-  }
-  // send a notify on the realm object
-  r = ctx.notify2(get_control_oid(), bl, 0, nullptr);
-  if (r < 0) {
-    ldout(cct, 0) << "Realm notify failed with " << r << dendl;
-    return r;
-  }
-  return 0;
-}
-
-int RGWRealm::notify_new_period(const RGWPeriod& period)
-{
-  bufferlist bl;
-  using ceph::encode;
-  // push the period to dependent zonegroups/zones
-  encode(RGWRealmNotify::ZonesNeedPeriod, bl);
-  encode(period, bl);
-  // reload the gateway with the new period
-  encode(RGWRealmNotify::Reload, bl);
-
-  return notify_zone(bl);
-}
-
-std::string RGWPeriodConfig::get_oid(const std::string& realm_id)
-{
-  if (realm_id.empty()) {
-    return "period_config.default";
-  }
-  return "period_config." + realm_id;
-}
-
-rgw_pool RGWPeriodConfig::get_pool(CephContext *cct)
-{
-  const auto& pool_name = cct->_conf->rgw_period_root_pool;
-  if (pool_name.empty()) {
-    return {RGW_DEFAULT_PERIOD_ROOT_POOL};
-  }
-  return {pool_name};
-}
-
-int RGWPeriodConfig::read(RGWRados *store, const std::string& realm_id)
-{
-  RGWObjectCtx obj_ctx(store);
-  const auto& pool = get_pool(store->ctx());
-  const auto& oid = get_oid(realm_id);
-  bufferlist bl;
-
-  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, nullptr, nullptr);
-  if (ret < 0) {
-    return ret;
-  }
-  using ceph::decode;
-  try {
-    auto iter = bl.cbegin();
-    decode(*this, iter);
-  } catch (buffer::error& err) {
-    return -EIO;
-  }
-  return 0;
-}
-
-int RGWPeriodConfig::write(RGWRados *store, const std::string& realm_id)
-{
-  const auto& pool = get_pool(store->ctx());
-  const auto& oid = get_oid(realm_id);
-  bufferlist bl;
-  using ceph::encode;
-  encode(*this, bl);
-  return rgw_put_system_obj(store, pool, oid, bl,
-                            false, nullptr, real_time(), nullptr);
-}
-
-int RGWPeriod::init(CephContext *_cct, RGWRados *_store, const string& period_realm_id,
-                   const string& period_realm_name, bool setup_obj)
-{
-  cct = _cct;
-  store = _store;
-  realm_id = period_realm_id;
-  realm_name = period_realm_name;
-
-  if (!setup_obj)
-    return 0;
-
-  return init(_cct, _store, setup_obj);
-}
-
-
-int RGWPeriod::init(CephContext *_cct, RGWRados *_store, bool setup_obj)
-{
-  cct = _cct;
-  store = _store;
-
-  if (!setup_obj)
-    return 0;
-
-  if (id.empty()) {
-    RGWRealm realm(realm_id, realm_name);
-    int ret = realm.init(cct, store);
-    if (ret < 0) {
-      ldout(cct, 0) << "RGWPeriod::init failed to init realm " << realm_name  << " id " << realm_id << " : " <<
-       cpp_strerror(-ret) << dendl;
-      return ret;
-    }
-    id = realm.get_current_period();
-    realm_id = realm.get_id();
-  }
-
-  if (!epoch) {
-    int ret = use_latest_epoch();
-    if (ret < 0) {
-      ldout(cct, 0) << "failed to use_latest_epoch period id " << id << " realm " << realm_name  << " id " << realm_id
-          << " : " << cpp_strerror(-ret) << dendl;
-      return ret;
-    }
-  }
-
-  return read_info();
-}
-
-
-int RGWPeriod::get_zonegroup(RGWZoneGroup& zonegroup, const string& zonegroup_id) {
-  map<string, RGWZoneGroup>::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;
-}
-
-bool RGWRados::get_redirect_zone_endpoint(string *endpoint)
-{
-  if (zone_public_config.redirect_zone.empty()) {
-    return false;
-  }
-
-  auto iter = zone_conn_map.find(zone_public_config.redirect_zone);
-  if (iter == zone_conn_map.end()) {
-    ldout(cct, 0) << "ERROR: cannot find entry for redirect zone: " << zone_public_config.redirect_zone << dendl;
-    return false;
-  }
-
-  RGWRESTConn *conn = iter->second;
-
-  int ret = conn->get_url(*endpoint);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR: redirect zone, conn->get_endpoint() returned ret=" << ret << dendl;
-    return false;
-  }
-
-  return true;
-}
-
-const string& RGWPeriod::get_latest_epoch_oid()
-{
-  if (cct->_conf->rgw_period_latest_epoch_info_oid.empty()) {
-    return period_latest_epoch_info_oid;
-  }
-  return cct->_conf->rgw_period_latest_epoch_info_oid;
-}
-
-const string& RGWPeriod::get_info_oid_prefix()
-{
-  return period_info_oid_prefix;
-}
-
-const string RGWPeriod::get_period_oid_prefix()
-{
-  return get_info_oid_prefix() + id;
-}
-
-const string RGWPeriod::get_period_oid()
-{
-  std::ostringstream oss;
-  oss << get_period_oid_prefix();
-  // skip the epoch for the staging period
-  if (id != get_staging_id(realm_id))
-    oss << "." << epoch;
-  return oss.str();
-}
-
-int RGWPeriod::read_latest_epoch(RGWPeriodLatestEpochInfo& info,
-                                 RGWObjVersionTracker *objv)
-{
-  string oid = get_period_oid_prefix() + get_latest_epoch_oid();
-
-  rgw_pool pool(get_pool(cct));
-  bufferlist bl;
-  RGWObjectCtx obj_ctx(store);
-  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, objv, nullptr);
-  if (ret < 0) {
-    ldout(cct, 1) << "error read_lastest_epoch " << pool << ":" << oid << dendl;
-    return ret;
-  }
-  try {
-    auto iter = bl.cbegin();
-    using ceph::decode;
-    decode(info, iter);
-  } catch (buffer::error& err) {
-    ldout(cct, 0) << "error decoding data from " << pool << ":" << oid << dendl;
-    return -EIO;
-  }
-
-  return 0;
-}
-
-int RGWPeriod::get_latest_epoch(epoch_t& latest_epoch)
-{
-  RGWPeriodLatestEpochInfo info;
-
-  int ret = read_latest_epoch(info);
-  if (ret < 0) {
-    return ret;
-  }
-
-  latest_epoch = info.epoch;
-
-  return 0;
-}
-
-int RGWPeriod::use_latest_epoch()
-{
-  RGWPeriodLatestEpochInfo info;
-  int ret = read_latest_epoch(info);
-  if (ret < 0) {
-    return ret;
-  }
-
-  epoch = info.epoch;
-
-  return 0;
-}
-
-int RGWPeriod::set_latest_epoch(epoch_t epoch, bool exclusive,
-                                RGWObjVersionTracker *objv)
-{
-  string oid = get_period_oid_prefix() + get_latest_epoch_oid();
-
-  rgw_pool pool(get_pool(cct));
-  bufferlist bl;
-
-  RGWPeriodLatestEpochInfo info;
-  info.epoch = epoch;
-
-  using ceph::encode;
-  encode(info, bl);
-
-  return rgw_put_system_obj(store, pool, oid, bl,
-                            exclusive, objv, real_time(), nullptr);
-}
-
-int RGWPeriod::update_latest_epoch(epoch_t epoch)
-{
-  static constexpr int MAX_RETRIES = 20;
-
-  for (int i = 0; i < MAX_RETRIES; i++) {
-    RGWPeriodLatestEpochInfo info;
-    RGWObjVersionTracker objv;
-    bool exclusive = false;
-
-    // read existing epoch
-    int r = read_latest_epoch(info, &objv);
-    if (r == -ENOENT) {
-      // use an exclusive create to set the epoch atomically
-      exclusive = true;
-      ldout(cct, 20) << "creating initial latest_epoch=" << epoch
-          << " for period=" << id << dendl;
-    } else if (r < 0) {
-      ldout(cct, 0) << "ERROR: failed to read latest_epoch" << dendl;
-      return r;
-    } else if (epoch <= info.epoch) {
-      r = -EEXIST; // fail with EEXIST if epoch is not newer
-      ldout(cct, 1) << "found existing latest_epoch " << info.epoch
-          << " >= given epoch " << epoch << ", returning r=" << r << dendl;
-      return r;
-    } else {
-      ldout(cct, 20) << "updating latest_epoch from " << info.epoch
-          << " -> " << epoch << " on period=" << id << dendl;
-    }
-
-    r = set_latest_epoch(epoch, exclusive, &objv);
-    if (r == -EEXIST) {
-      continue; // exclusive create raced with another update, retry
-    } else if (r == -ECANCELED) {
-      continue; // write raced with a conflicting version, retry
-    }
-    if (r < 0) {
-      ldout(cct, 0) << "ERROR: failed to write latest_epoch" << dendl;
-      return r;
-    }
-    return 0; // return success
-  }
-
-  return -ECANCELED; // fail after max retries
-}
-
-int RGWPeriod::delete_obj()
-{
-  rgw_pool pool(get_pool(cct));
-
-  // delete the object for each period epoch
-  for (epoch_t e = 1; e <= epoch; e++) {
-    RGWPeriod p{get_id(), e};
-    rgw_raw_obj oid{pool, p.get_period_oid()};
-    int ret = store->delete_system_obj(oid);
-    if (ret < 0) {
-      ldout(cct, 0) << "WARNING: failed to delete period object " << oid
-          << ": " << cpp_strerror(-ret) << dendl;
-    }
-  }
-
-  // delete the .latest_epoch object
-  rgw_raw_obj oid{pool, get_period_oid_prefix() + get_latest_epoch_oid()};
-  int ret = store->delete_system_obj(oid);
-  if (ret < 0) {
-    ldout(cct, 0) << "WARNING: failed to delete period object " << oid
-        << ": " << cpp_strerror(-ret) << dendl;
-  }
-  return ret;
-}
-
-int RGWPeriod::read_info()
-{
-  rgw_pool pool(get_pool(cct));
-
-  bufferlist bl;
-
-  RGWObjectCtx obj_ctx(store);
-  int ret = rgw_get_system_obj(store, obj_ctx, pool, get_period_oid(), bl, NULL, NULL);
-  if (ret < 0) {
-    ldout(cct, 0) << "failed reading obj info from " << pool << ":" << get_period_oid() << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  try {
-    using ceph::decode;
-    auto iter = bl.cbegin();
-    decode(*this, iter);
-  } catch (buffer::error& err) {
-    ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << get_period_oid() << dendl;
-    return -EIO;
-  }
-
-  return 0;
-}
-
-int RGWPeriod::create(bool exclusive)
-{
-  int ret;
-  
-  /* create unique id */
-  uuid_d new_uuid;
-  char uuid_str[37];
-  new_uuid.generate_random();
-  new_uuid.print(uuid_str);
-  id = uuid_str;
-
-  epoch = FIRST_EPOCH;
-
-  period_map.id = id;
-  
-  ret = store_info(exclusive);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR:  storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  ret = set_latest_epoch(epoch);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR: setting latest epoch " << id << ": " << cpp_strerror(-ret) << dendl;
-  }
-
-  return ret;
-}
-
-int RGWPeriod::store_info(bool exclusive)
-{
-  rgw_pool pool(get_pool(cct));
-
-  string oid = get_period_oid();
-  bufferlist bl;
-  using ceph::encode;
-  encode(*this, bl);
-
-  return rgw_put_system_obj(store, pool, oid, bl,
-                            exclusive, NULL, real_time(), NULL);
-}
-
-rgw_pool RGWPeriod::get_pool(CephContext *cct)
-{
-  if (cct->_conf->rgw_period_root_pool.empty()) {
-    return rgw_pool(RGW_DEFAULT_PERIOD_ROOT_POOL);
-  }
-  return rgw_pool(cct->_conf->rgw_period_root_pool);
-}
-
-int RGWPeriod::add_zonegroup(const RGWZoneGroup& zonegroup)
-{
-  if (zonegroup.realm_id != realm_id) {
-    return 0;
-  }
-  int ret = period_map.update(zonegroup, cct);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR: updating period map: " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  return store_info(false);
-}
-
-int RGWPeriod::update()
-{
-  ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << get_id() << dendl;
-  list<string> zonegroups;
-  int ret = store->list_zonegroups(zonegroups);
-  if (ret < 0) {
-    ldout(cct, 0) << "ERROR: failed to list zonegroups: " << cpp_strerror(-ret) << dendl;
-    return ret;
-  }
-
-  // clear zone short ids of removed zones. period_map.update() will add the
-  // remaining zones back
-  period_map.short_zone_ids.clear();
-
-  for (auto& iter : zonegroups) {
-    RGWZoneGroup zg(string(), iter);
-    ret = zg.init(cct, store);
-    if (ret < 0) {
-      ldout(cct, 0) << "WARNING: zg.init() failed: " << cpp_strerror(-ret) << dendl;
-      continue;
-    }
-
-    if (zg.realm_id != realm_id) {
-      ldout(cct, 20) << "skipping zonegroup " << zg.get_name() << " zone realm id " << zg.realm_id << ", not on our realm " << realm_id << dendl;
-      continue;
-    }
-
-    if (zg.master_zone.empty()) {
-      ldout(cct, 0) << "ERROR: zonegroup " << zg.get_name() << " should have a master zone " << dendl;
-      return -EINVAL;
-    }  
-    
-    if (zg.is_master_zonegroup()) {
-      master_zonegroup = zg.get_id();
-      master_zone = zg.master_zone;
-    }
-
-    int ret = period_map.update(zg, cct);
-    if (ret < 0) {
-      return ret;
-    }
-  }
-
-  ret = period_config.read(store, realm_id);
-  if (ret < 0 && ret != -ENOENT) {
-    ldout(cct, 0) << "ERROR: failed to read period config: "
-        << cpp_strerror(ret) << dendl;
-    return ret;
-  }
-  return 0;
-}
-
-int RGWPeriod::reflect()
-{
-  for (auto& iter : period_map.zonegroups) {
-    RGWZoneGroup& zg = iter.second;
-    zg.reinit_instance(cct, store);
-    int r = zg.write(false);
-    if (r < 0) {
-      ldout(cct, 0) << "ERROR: failed to store zonegroup info for zonegroup=" << iter.first << ": " << cpp_strerror(-r) << dendl;
-      return r;
-    }
-    if (zg.is_master_zonegroup()) {
-      // set master as default if no default exists
-      r = zg.set_as_default(true);
-      if (r == 0) {
-        ldout(cct, 1) << "Set the period's master zonegroup " << zg.get_id()
-            << " as the default" << dendl;
-      }
-    }
-  }
-
-  int r = period_config.write(store, realm_id);
-  if (r < 0) {
-    ldout(cct, 0) << "ERROR: failed to store period config: "
-        << cpp_strerror(-r) << dendl;
-    return r;
-  }
-  return 0;
-}
-
-void RGWPeriod::fork()
-{
-  ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << id << dendl;
-  predecessor_uuid = id;
-  id = get_staging_id(realm_id);
-  period_map.reset();
-  realm_epoch++;
-}
-
-static int read_sync_status(RGWRados *store, rgw_meta_sync_status *sync_status)
-{
-  // initialize a sync status manager to read the status
-  RGWMetaSyncStatusManager mgr(store, store->get_async_rados());
-  int r = mgr.init();
-  if (r < 0) {
-    return r;
-  }
-  r = mgr.read_sync_status(sync_status);
-  mgr.stop();
-  return r;
-}
-
-int RGWPeriod::update_sync_status(const RGWPeriod &current_period,
-                                  std::ostream& error_stream,
-                                  bool force_if_stale)
-{
-  rgw_meta_sync_status status;
-  int r = read_sync_status(store, &status);
-  if (r < 0) {
-    ldout(cct, 0) << "period failed to read sync status: "
-        << cpp_strerror(-r) << dendl;
-    return r;
-  }
-
-  std::vector<std::string> 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;
-}
-
-int RGWPeriod::commit(RGWRealm& realm, const RGWPeriod& current_period,
-                      std::ostream& error_stream, bool force_if_stale)
-{
-  ldout(cct, 20) << __func__ << " realm " << realm.get_id() << " period " << current_period.get_id() << dendl;
-  // gateway must be in the master zone to commit
-  if (master_zone != store->get_zone_params().get_id()) {
-    error_stream << "Cannot commit period on zone "
-        << store->get_zone_params().get_id() << ", it must be sent to "
-        "the period's master zone " << master_zone << '.' << std::endl;
-    return -EINVAL;
-  }
-  // period predecessor must match current period
-  if (predecessor_uuid != current_period.get_id()) {
-    error_stream << "Period predecessor " << predecessor_uuid
-        << " does not match current period " << current_period.get_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 (realm_epoch != current_period.get_realm_epoch() + 1) {
-    error_stream << "Period's realm epoch " << realm_epoch
-        << " does not come directly after current realm epoch "
-        << current_period.get_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 (master_zone != current_period.get_master_zone()) {
-    // store the current metadata sync status in the period
-    int r = update_sync_status(current_period, error_stream, force_if_stale);
-    if (r < 0) {
-      ldout(cct, 0) << "failed to update metadata sync status: "
-          << cpp_strerror(-r) << dendl;
-      return r;
-    }
-    // create an object with a new period id
-    r = create(true);
-    if (r < 0) {
-      ldout(cct, 0) << "failed to create new period: " << cpp_strerror(-r) << dendl;
-      return r;
-    }
-    // set as current period
-    r = realm.set_current_period(*this);
-    if (r < 0) {
-      ldout(cct, 0) << "failed to update realm's current period: "
-          << cpp_strerror(-r) << dendl;
-      return r;
-    }
-    ldout(cct, 4) << "Promoted to master zone and committed new period "
-        << id << dendl;
-    realm.notify_new_period(*this);
-    return 0;
-  }
-  // period must be based on current epoch
-  if (epoch != current_period.get_epoch()) {
-    error_stream << "Period epoch " << epoch << " does not match "
-        "predecessor epoch " << current_period.get_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
-  set_id(current_period.get_id());
-  set_epoch(current_period.get_epoch() + 1);
-  set_predecessor(current_period.get_predecessor());
-  realm_epoch = current_period.get_realm_epoch();
-  // write the period to rados
-  int r = store_info(false);
-  if (r < 0) {
-    ldout(cct, 0) << "failed to store period: " << cpp_strerror(-r) << dendl;
-    return r;
-  }
-  // set as latest epoch
-  r = update_latest_epoch(epoch);
-  if (r == -EEXIST) {
-    // already have this epoch (or a more recent one)
-    return 0;
-  }
-  if (r < 0) {
-    ldout(cct, 0) << "failed to set latest epoch: " << cpp_strerror(-r) << dendl;
-    return r;
-  }
-  r = reflect();
-  if (r < 0) {
-    ldout(cct, 0) << "failed to update local objects: " << cpp_strerror(-r) << dendl;
-    return r;
-  }
-  ldout(cct, 4) << "Committed new epoch " << epoch
-      << " for period " << id << dendl;
-  realm.notify_new_period(*this);
-  return 0;
-}
-
-int RGWZoneParams::create_default(bool old_format)
-{
-  name = default_zone_name;
-
-  int r = create();
-  if (r < 0) {
-    return r;
-  }
-
-  if (old_format) {
-    name = id;
-  }
-
-  return r;
-}
-
-
-int get_zones_pool_set(CephContext* cct,
-                       RGWRados* store,
-                       const list<string>& zones,
-                       const string& my_zone_id,
-                       set<rgw_pool>& pool_names)
-{
-  for(auto const& iter : zones) {
-    RGWZoneParams zone(iter);
-    int r = zone.init(cct, store);
-    if (r < 0) {
-      ldout(cct, 0) << "Error: init zone " << iter << ":" << cpp_strerror(-r) << dendl;
-      return r;
-    }
-    if (zone.get_id() != my_zone_id) {
-      pool_names.insert(zone.domain_root);
-      pool_names.insert(zone.metadata_heap);
-      pool_names.insert(zone.control_pool);
-      pool_names.insert(zone.gc_pool);
-      pool_names.insert(zone.log_pool);
-      pool_names.insert(zone.intent_log_pool);
-      pool_names.insert(zone.usage_log_pool);
-      pool_names.insert(zone.user_keys_pool);
-      pool_names.insert(zone.user_email_pool);
-      pool_names.insert(zone.user_swift_pool);
-      pool_names.insert(zone.user_uid_pool);
-      pool_names.insert(zone.otp_pool);
-      pool_names.insert(zone.roles_pool);
-      pool_names.insert(zone.reshard_pool);
-      for(auto& iter : zone.placement_pools) {
-       pool_names.insert(iter.second.index_pool);
-       pool_names.insert(iter.second.data_pool);
-       pool_names.insert(iter.second.data_extra_pool);
-      }
-    }
-  }
-  return 0;
-}
-
-rgw_pool fix_zone_pool_dup(set<rgw_pool> pools,
-                           const string& default_prefix,
-                           const string& default_suffix,
-                           const rgw_pool& suggested_pool)
-{
-  string suggested_name = suggested_pool.to_str();
-
-  string prefix = default_prefix;
-  string suffix = default_suffix;
-
-  if (!suggested_pool.empty()) {
-    prefix = suggested_name.substr(0, suggested_name.find("."));
-    suffix = suggested_name.substr(prefix.length());
-  }
-
-  rgw_pool pool(prefix + suffix);
-  
-  if (pools.find(pool) == pools.end()) {
-    return pool;
-  } else {
-    while(true) {
-      pool =  prefix + "_" + std::to_string(std::rand()) + suffix;
-      if (pools.find(pool) == pools.end()) {
-       return pool;
-      }
-    }
-  }  
-}
-
-int RGWZoneParams::fix_pool_names()
-{
-
-  list<string> zones;
-  int r = store->list_zones(zones);
-  if (r < 0) {
-    ldout(cct, 10) << "WARNING: store->list_zones() returned r=" << r << dendl;
-  }
-
-  set<rgw_pool> pools;
-  r = get_zones_pool_set(cct, store, zones, id, pools);
-  if (r < 0) {
-    ldout(cct, 0) << "Error: get_zones_pool_names" << r << dendl;
-    return r;
-  }
-
-  domain_root = fix_zone_pool_dup(pools, name, ".rgw.meta:root", domain_root);
-  if (!metadata_heap.name.empty()) {
-    metadata_heap = fix_zone_pool_dup(pools, name, ".rgw.meta:heap", metadata_heap);
-  }
-  control_pool = fix_zone_pool_dup(pools, name, ".rgw.control", control_pool);
-  gc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:gc", gc_pool);
-  lc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:lc", lc_pool);
-  log_pool = fix_zone_pool_dup(pools, name, ".rgw.log", log_pool);
-  intent_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:intent", intent_log_pool);
-  usage_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:usage", usage_log_pool);
-  user_keys_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.keys", user_keys_pool);
-  user_email_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.email", user_email_pool);
-  user_swift_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.swift", user_swift_pool);
-  user_uid_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.uid", user_uid_pool);
-  roles_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:roles", roles_pool);
-  reshard_pool = fix_zone_pool_dup(pools, name, ".rgw.log:reshard", reshard_pool);
-  otp_pool = fix_zone_pool_dup(pools, name, ".rgw.otp", otp_pool);
-
-  for(auto& iter : placement_pools) {
-    iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix,
-                                               iter.second.index_pool);
-    iter.second.data_pool = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
-                                              iter.second.data_pool);
-    iter.second.data_extra_pool= fix_zone_pool_dup(pools, name, "." + default_storage_extra_pool_suffix,
-                                                   iter.second.data_extra_pool);
-  }
-
-  return 0;
-}
-
-int RGWZoneParams::create(bool exclusive)
-{
-  /* check for old pools config */
-  rgw_raw_obj obj(domain_root, avail_pools);
-  int r = store->raw_obj_stat(obj, NULL, NULL, NULL, NULL, NULL, NULL);
-  if (r < 0) {
-    ldout(store->ctx(), 10) << "couldn't find old data placement pools config, setting up new ones for the zone" << dendl;
-    /* a new system, let's set new placement info */
-    RGWZonePlacementInfo default_placement;
-    default_placement.index_pool = name + "." + default_bucket_index_pool_suffix;
-    default_placement.data_pool =  name + "." + default_storage_pool_suffix;
-    default_placement.data_extra_pool = name + "." + default_storage_extra_pool_suffix;
-    placement_pools["default-placement"] = default_placement;
-  }
-
-  r = fix_pool_names();
-  if (r < 0) {
-    ldout(cct, 0) << "ERROR: fix_pool_names returned r=" << r << dendl;
-    return r;
-  }
-
-  r = RGWSystemMetaObj::create(exclusive);
-  if (r < 0) {
-    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_as_default(true);
-  if (r < 0 && r != -EEXIST) {
-    ldout(cct, 10) << "WARNING: failed to set zone as default, r=" << r << dendl;
-  }
-
-  return 0;
-}
-
-rgw_pool RGWZoneParams::get_pool(CephContext *cct)
-{
-  if (cct->_conf->rgw_zone_root_pool.empty()) {
-    return rgw_pool(RGW_DEFAULT_ZONE_ROOT_POOL);
-  }
-
-  return rgw_pool(cct->_conf->rgw_zone_root_pool);
-}
-
-const string RGWZoneParams::get_default_oid(bool old_format)
-{
-  if (old_format) {
-    return cct->_conf->rgw_default_zone_info_oid;
-  }
-
-  return cct->_conf->rgw_default_zone_info_oid + "." + realm_id;
-}
-
-const string& RGWZoneParams::get_names_oid_prefix()
-{
-  return zone_names_oid_prefix;
-}
-
-const string& RGWZoneParams::get_info_oid_prefix(bool old_format)
-{
-  return zone_info_oid_prefix;
-}
-
-const string& RGWZoneParams::get_predefined_name(CephContext *cct) {
-  return cct->_conf->rgw_zone;
-}
-
-int RGWZoneParams::init(CephContext *cct, RGWRados *store, bool setup_obj, bool old_format)
-{
-  if (name.empty()) {
-    name = cct->_conf->rgw_zone;
-  }
-
-  return RGWSystemMetaObj::init(cct, store, setup_obj, old_format);
-}
-
-int RGWZoneParams::read_default_id(string& default_id, bool old_format)
-{
-  if (realm_id.empty()) {
-    /* try using default realm */
-    RGWRealm realm;
-    int ret = realm.init(cct, store);
-    //no default realm exist
-    if (ret < 0) {
-      return read_id(default_zone_name, default_id);
-    }
-    realm_id = realm.get_id();
-  }
-
-  return RGWSystemMetaObj::read_default_id(default_id, old_format);
-}
-
-
-int RGWZoneParams::set_as_default(bool exclusive)
-{
-  if (realm_id.empty()) {
-    /* try using default realm */
-    RGWRealm realm;
-    int ret = realm.init(cct, store);
-    if (ret < 0) {
-      ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
-      return -EINVAL;
-    }
-    realm_id = realm.get_id();
-  }
-
-  return RGWSystemMetaObj::set_as_default(exclusive);
-}
-
-const string& RGWZoneParams::get_compression_type(const string& placement_rule) const
-{
-  static const std::string NONE{"none"};
-  auto p = placement_pools.find(placement_rule);
-  if (p == placement_pools.end()) {
-    return NONE;
-  }
-  const auto& type = p->second.compression_type;
-  return !type.empty() ? type : NONE;
-}
-
-void RGWPeriodMap::encode(bufferlist& bl) const {
-  ENCODE_START(2, 1, bl);
-  encode(id, bl);
-  encode(zonegroups, bl);
-  encode(master_zonegroup, bl);
-  encode(short_zone_ids, bl);
-  ENCODE_FINISH(bl);
-}
-
-void RGWPeriodMap::decode(bufferlist::const_iterator& bl) {
-  DECODE_START(2, bl);
-  decode(id, bl);
-  decode(zonegroups, bl);
-  decode(master_zonegroup, bl);
-  if (struct_v >= 2) {
-    decode(short_zone_ids, bl);
-  }
-  DECODE_FINISH(bl);
-
-  zonegroups_by_api.clear();
-  for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
-       iter != zonegroups.end(); ++iter) {
-    RGWZoneGroup& zonegroup = iter->second;
-    zonegroups_by_api[zonegroup.api_name] = zonegroup;
-    if (zonegroup.is_master_zonegroup()) {
-      master_zonegroup = zonegroup.get_id();
-    }
-  }
-}
-
-// 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;
-  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() <<dendl;
-    return -EINVAL;
-  }
-  map<string, RGWZoneGroup>::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;
-}
-
-int RGWZoneGroupMap::read(CephContext *cct, RGWRados *store)
-{
-
-  RGWPeriod period;
-  int ret = period.init(cct, store);
-  if (ret < 0) {
-    cerr << "failed to read current period info: " << cpp_strerror(ret);
-    return ret;
-  }
-       
-  bucket_quota = period.get_config().bucket_quota;
-  user_quota = period.get_config().user_quota;
-  zonegroups = period.get_map().zonegroups;
-  zonegroups_by_api = period.get_map().zonegroups_by_api;
-  master_zonegroup = period.get_map().master_zonegroup;
-
-  return 0;
-}
-
-void RGWRegionMap::encode(bufferlist& bl) const {
-  ENCODE_START( 3, 1, bl);
-  encode(regions, bl);
-  encode(master_region, bl);
-  encode(bucket_quota, bl);
-  encode(user_quota, bl);
-  ENCODE_FINISH(bl);
-}
-
-void RGWRegionMap::decode(bufferlist::const_iterator& bl) {
-  DECODE_START(3, bl);
-  decode(regions, bl);
-  decode(master_region, bl);
-  if (struct_v >= 2)
-    decode(bucket_quota, bl);
-  if (struct_v >= 3)
-    decode(user_quota, bl);
-  DECODE_FINISH(bl);
-}
-
-void RGWZoneGroupMap::encode(bufferlist& bl) const {
-  ENCODE_START( 3, 1, bl);
-  encode(zonegroups, bl);
-  encode(master_zonegroup, bl);
-  encode(bucket_quota, bl);
-  encode(user_quota, bl);
-  ENCODE_FINISH(bl);
-}
-
-void RGWZoneGroupMap::decode(bufferlist::const_iterator& bl) {
-  DECODE_START(3, bl);
-  decode(zonegroups, bl);
-  decode(master_zonegroup, bl);
-  if (struct_v >= 2)
-    decode(bucket_quota, bl);
-  if (struct_v >= 3)
-    decode(user_quota, bl);
-  DECODE_FINISH(bl);
-
-  zonegroups_by_api.clear();
-  for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
-       iter != zonegroups.end(); ++iter) {
-    RGWZoneGroup& zonegroup = iter->second;
-    zonegroups_by_api[zonegroup.api_name] = zonegroup;
-    if (zonegroup.is_master_zonegroup()) {
-      master_zonegroup = zonegroup.get_name();
-    }
-  }
-}
-
 void RGWObjVersionTracker::prepare_op_for_read(ObjectReadOperation *op)
 {
   obj_version *check_objv = version_for_check();
index d48d95678372ef6ba51c1cb5beb5b8418b3ecd95..7f7c7413e50ad21aaab839b5dca11f8c08f681ad 100644 (file)
@@ -27,6 +27,8 @@
 #include "rgw_sync_module.h"
 #include "rgw_sync_log_trim.h"
 
+#include "services/svc_zone.h"
+
 class RGWWatcher;
 class SafeTimer;
 class ACLOwner;
@@ -44,6 +46,8 @@ struct RGWZoneGroup;
 struct RGWZoneParams;
 class RGWReshard;
 class RGWReshardWait;
+struct RGWZone;
+struct RGWPeriod;
 
 /* flags for put_obj_meta() */
 #define PUT_OBJ_CREATE      0x01
@@ -1031,943 +1035,6 @@ struct RGWNameToId {
 };
 WRITE_CLASS_ENCODER(RGWNameToId)
 
-class RGWSystemMetaObj {
-protected:
-  string id;
-  string name;
-
-  CephContext *cct;
-  RGWRados *store;
-
-  int store_name(bool exclusive);
-  int store_info(bool exclusive);
-  int read_info(const string& obj_id, bool old_format = false);
-  int read_id(const string& obj_name, string& obj_id);
-  int read_default(RGWDefaultSystemMetaObjInfo& default_info,
-                  const string& oid);
-  /* read and use default id */
-  int use_default(bool old_format = false);
-
-public:
-  RGWSystemMetaObj() : cct(NULL), store(NULL) {}
-  RGWSystemMetaObj(const string& _name): name(_name), cct(NULL), store(NULL)  {}
-  RGWSystemMetaObj(const string& _id, const string& _name) : id(_id), name(_name), cct(NULL), store(NULL) {}
-  RGWSystemMetaObj(CephContext *_cct, RGWRados *_store): cct(_cct), store(_store){}
-  RGWSystemMetaObj(const string& _name, CephContext *_cct, RGWRados *_store): name(_name), cct(_cct), store(_store){}
-  const string& get_name() const { return name; }
-  const string& get_id() const { return id; }
-
-  void set_name(const string& _name) { name = _name;}
-  void set_id(const string& _id) { id = _id;}
-  void clear_id() { id.clear(); }
-
-  virtual ~RGWSystemMetaObj() {}
-
-  virtual void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    encode(id, bl);
-    encode(name, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  virtual void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
-    decode(id, bl);
-    decode(name, bl);
-    DECODE_FINISH(bl);
-  }
-
-  void reinit_instance(CephContext *_cct, RGWRados *_store) {
-    cct = _cct;
-    store = _store;
-  }
-  int init(CephContext *_cct, RGWRados *_store, bool setup_obj = true, bool old_format = false);
-  virtual int read_default_id(string& default_id, bool old_format = false);
-  virtual int set_as_default(bool exclusive = false);
-  int delete_default();
-  virtual int create(bool exclusive = true);
-  int delete_obj(bool old_format = false);
-  int rename(const string& new_name);
-  int update() { return store_info(false);}
-  int update_name() { return store_name(false);}
-  int read();
-  int write(bool exclusive);
-
-  virtual rgw_pool get_pool(CephContext *cct) = 0;
-  virtual const string get_default_oid(bool old_format = false) = 0;
-  virtual const string& get_names_oid_prefix() = 0;
-  virtual const string& get_info_oid_prefix(bool old_format = false) = 0;
-  virtual const string& get_predefined_name(CephContext *cct) = 0;
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWSystemMetaObj)
-
-struct RGWZonePlacementInfo {
-  rgw_pool index_pool;
-  rgw_pool data_pool;
-  rgw_pool data_extra_pool; /* if not set we should use data_pool */
-  RGWBucketIndexType index_type;
-  std::string compression_type;
-
-  RGWZonePlacementInfo() : index_type(RGWBIType_Normal) {}
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(6, 1, bl);
-    encode(index_pool.to_str(), bl);
-    encode(data_pool.to_str(), bl);
-    encode(data_extra_pool.to_str(), bl);
-    encode((uint32_t)index_type, bl);
-    encode(compression_type, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(6, bl);
-    string index_pool_str;
-    string data_pool_str;
-    decode(index_pool_str, bl);
-    index_pool = rgw_pool(index_pool_str);
-    decode(data_pool_str, bl);
-    data_pool = rgw_pool(data_pool_str);
-    if (struct_v >= 4) {
-      string data_extra_pool_str;
-      decode(data_extra_pool_str, bl);
-      data_extra_pool = rgw_pool(data_extra_pool_str);
-    }
-    if (struct_v >= 5) {
-      uint32_t it;
-      decode(it, bl);
-      index_type = (RGWBucketIndexType)it;
-    }
-    if (struct_v >= 6) {
-      decode(compression_type, bl);
-    }
-    DECODE_FINISH(bl);
-  }
-  const rgw_pool& get_data_extra_pool() const {
-    if (data_extra_pool.empty()) {
-      return data_pool;
-    }
-    return data_extra_pool;
-  }
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWZonePlacementInfo)
-
-struct RGWZoneParams : RGWSystemMetaObj {
-  rgw_pool domain_root;
-  rgw_pool metadata_heap;
-  rgw_pool control_pool;
-  rgw_pool gc_pool;
-  rgw_pool lc_pool;
-  rgw_pool log_pool;
-  rgw_pool intent_log_pool;
-  rgw_pool usage_log_pool;
-
-  rgw_pool user_keys_pool;
-  rgw_pool user_email_pool;
-  rgw_pool user_swift_pool;
-  rgw_pool user_uid_pool;
-  rgw_pool roles_pool;
-  rgw_pool reshard_pool;
-  rgw_pool otp_pool;
-
-  RGWAccessKey system_key;
-
-  map<string, RGWZonePlacementInfo> placement_pools;
-
-  string realm_id;
-
-  JSONFormattable tier_config;
-
-  RGWZoneParams() : RGWSystemMetaObj() {}
-  explicit RGWZoneParams(const string& name) : RGWSystemMetaObj(name){}
-  RGWZoneParams(const string& id, const string& name) : RGWSystemMetaObj(id, name) {}
-  RGWZoneParams(const string& id, const string& name, const string& _realm_id)
-    : RGWSystemMetaObj(id, name), realm_id(_realm_id) {}
-
-  rgw_pool get_pool(CephContext *cct) override;
-  const string get_default_oid(bool old_format = false) override;
-  const string& get_names_oid_prefix() override;
-  const string& get_info_oid_prefix(bool old_format = false) override;
-  const string& get_predefined_name(CephContext *cct) override;
-
-  int init(CephContext *_cct, RGWRados *_store, bool setup_obj = true,
-          bool old_format = false);
-  using RGWSystemMetaObj::init;
-  int read_default_id(string& default_id, bool old_format = false) override;
-  int set_as_default(bool exclusive = false) override;
-  int create_default(bool old_format = false);
-  int create(bool exclusive = true) override;
-  int fix_pool_names();
-
-  const string& get_compression_type(const string& placement_rule) const;
-  
-  void encode(bufferlist& bl) const override {
-    ENCODE_START(12, 1, bl);
-    encode(domain_root, bl);
-    encode(control_pool, bl);
-    encode(gc_pool, bl);
-    encode(log_pool, bl);
-    encode(intent_log_pool, bl);
-    encode(usage_log_pool, bl);
-    encode(user_keys_pool, bl);
-    encode(user_email_pool, bl);
-    encode(user_swift_pool, bl);
-    encode(user_uid_pool, bl);
-    RGWSystemMetaObj::encode(bl);
-    encode(system_key, bl);
-    encode(placement_pools, bl);
-    encode(metadata_heap, bl);
-    encode(realm_id, bl);
-    encode(lc_pool, bl);
-    map<string, string, ltstr_nocase> old_tier_config;
-    encode(old_tier_config, bl);
-    encode(roles_pool, bl);
-    encode(reshard_pool, bl);
-    encode(otp_pool, bl);
-    encode(tier_config, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) override {
-    DECODE_START(12, bl);
-    decode(domain_root, bl);
-    decode(control_pool, bl);
-    decode(gc_pool, bl);
-    decode(log_pool, bl);
-    decode(intent_log_pool, bl);
-    decode(usage_log_pool, bl);
-    decode(user_keys_pool, bl);
-    decode(user_email_pool, bl);
-    decode(user_swift_pool, bl);
-    decode(user_uid_pool, bl);
-    if (struct_v >= 6) {
-      RGWSystemMetaObj::decode(bl);
-    } else if (struct_v >= 2) {
-      decode(name, bl);
-      id = name;
-    }
-    if (struct_v >= 3)
-      decode(system_key, bl);
-    if (struct_v >= 4)
-      decode(placement_pools, bl);
-    if (struct_v >= 5)
-      decode(metadata_heap, bl);
-    if (struct_v >= 6) {
-      decode(realm_id, bl);
-    }
-    if (struct_v >= 7) {
-      decode(lc_pool, bl);
-    } else {
-      lc_pool = log_pool.name + ":lc";
-    }
-    map<string, string, ltstr_nocase> old_tier_config;
-    if (struct_v >= 8) {
-      decode(old_tier_config, bl);
-    }
-    if (struct_v >= 9) {
-      decode(roles_pool, bl);
-    } else {
-      roles_pool = name + ".rgw.meta:roles";
-    }
-    if (struct_v >= 10) {
-      decode(reshard_pool, bl);
-    } else {
-      reshard_pool = log_pool.name + ":reshard";
-    }
-    if (struct_v >= 11) {
-      ::decode(otp_pool, bl);
-    } else {
-      otp_pool = name + ".rgw.otp";
-    }
-    if (struct_v >= 12) {
-      ::decode(tier_config, bl);
-    } else {
-      for (auto& kv : old_tier_config) {
-        tier_config.set(kv.first, kv.second);
-      }
-    }
-    DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-  static void generate_test_instances(list<RGWZoneParams*>& o);
-
-  bool get_placement(const string& placement_id, RGWZonePlacementInfo *placement) const {
-    auto iter = placement_pools.find(placement_id);
-    if (iter == placement_pools.end()) {
-      return false;
-    }
-    *placement = iter->second;
-    return true;
-  }
-
-  /*
-   * return data pool of the head object
-   */
-  bool get_head_data_pool(const string& placement_id, const rgw_obj& obj, rgw_pool *pool) const {
-    const rgw_data_placement_target& explicit_placement = obj.bucket.explicit_placement;
-    if (!explicit_placement.data_pool.empty()) {
-      if (!obj.in_extra_data) {
-        *pool = explicit_placement.data_pool;
-      } else {
-        *pool = explicit_placement.get_data_extra_pool();
-      }
-      return true;
-    }
-    if (placement_id.empty()) {
-      return false;
-    }
-    auto iter = placement_pools.find(placement_id);
-    if (iter == placement_pools.end()) {
-      return false;
-    }
-    if (!obj.in_extra_data) {
-      *pool = iter->second.data_pool;
-    } else {
-      *pool = iter->second.get_data_extra_pool();
-    }
-    return true;
-  }
-};
-WRITE_CLASS_ENCODER(RGWZoneParams)
-
-struct RGWZone {
-  string id;
-  string name;
-  list<string> endpoints;
-  bool log_meta;
-  bool log_data;
-  bool read_only;
-  string tier_type;
-
-  string redirect_zone;
-
-/**
- * Represents the number of shards for the bucket index object, a value of zero
- * indicates there is no sharding. By default (no sharding, the name of the object
- * is '.dir.{marker}', with sharding, the name is '.dir.{marker}.{sharding_id}',
- * sharding_id is zero-based value. It is not recommended to set a too large value
- * (e.g. thousand) as it increases the cost for bucket listing.
- */
-  uint32_t bucket_index_max_shards;
-
-  bool sync_from_all;
-  set<string> sync_from; /* list of zones to sync from */
-
-  RGWZone() : log_meta(false), log_data(false), read_only(false), bucket_index_max_shards(0),
-              sync_from_all(true) {}
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(7, 1, bl);
-    encode(name, bl);
-    encode(endpoints, bl);
-    encode(log_meta, bl);
-    encode(log_data, bl);
-    encode(bucket_index_max_shards, bl);
-    encode(id, bl);
-    encode(read_only, bl);
-    encode(tier_type, bl);
-    encode(sync_from_all, bl);
-    encode(sync_from, bl);
-    encode(redirect_zone, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(7, bl);
-    decode(name, bl);
-    if (struct_v < 4) {
-      id = name;
-    }
-    decode(endpoints, bl);
-    if (struct_v >= 2) {
-      decode(log_meta, bl);
-      decode(log_data, bl);
-    }
-    if (struct_v >= 3) {
-      decode(bucket_index_max_shards, bl);
-    }
-    if (struct_v >= 4) {
-      decode(id, bl);
-      decode(read_only, bl);
-    }
-    if (struct_v >= 5) {
-      decode(tier_type, bl);
-    }
-    if (struct_v >= 6) {
-      decode(sync_from_all, bl);
-      decode(sync_from, bl);
-    }
-    if (struct_v >= 7) {
-      decode(redirect_zone, bl);
-    }
-    DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-  static void generate_test_instances(list<RGWZone*>& o);
-
-  bool is_read_only() { return read_only; }
-
-  bool syncs_from(const string& zone_id) const {
-    return (sync_from_all || sync_from.find(zone_id) != sync_from.end());
-  }
-};
-WRITE_CLASS_ENCODER(RGWZone)
-
-struct RGWDefaultZoneGroupInfo {
-  string default_zonegroup;
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    encode(default_zonegroup, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
-    decode(default_zonegroup, bl);
-    DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-  //todo: implement ceph-dencoder
-};
-WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo)
-
-struct RGWZoneGroupPlacementTarget {
-  string name;
-  set<string> tags;
-
-  bool user_permitted(list<string>& user_tags) const {
-    if (tags.empty()) {
-      return true;
-    }
-    for (auto& rule : user_tags) {
-      if (tags.find(rule) != tags.end()) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    encode(name, bl);
-    encode(tags, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
-    decode(name, bl);
-    decode(tags, bl);
-    DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTarget)
-
-
-struct RGWZoneGroup : public RGWSystemMetaObj {
-  string api_name;
-  list<string> endpoints;
-  bool is_master = false;
-
-  string master_zone;
-  map<string, RGWZone> zones;
-
-  map<string, RGWZoneGroupPlacementTarget> placement_targets;
-  string default_placement;
-
-  list<string> hostnames;
-  list<string> hostnames_s3website;
-  // TODO: Maybe convert hostnames to a map<string,list<string>> for
-  // endpoint_type->hostnames
-/*
-20:05 < _robbat21irssi> maybe I do someting like: if (hostname_map.empty()) { populate all map keys from hostnames; };
-20:05 < _robbat21irssi> but that's a later compatability migration planning bit
-20:06 < yehudasa> more like if (!hostnames.empty()) {
-20:06 < yehudasa> for (list<string>::iterator iter = hostnames.begin(); iter != hostnames.end(); ++iter) {
-20:06 < yehudasa> hostname_map["s3"].append(iter->second);
-20:07 < yehudasa> hostname_map["s3website"].append(iter->second);
-20:07 < yehudasa> s/append/push_back/g
-20:08 < _robbat21irssi> inner loop over APIs
-20:08 < yehudasa> yeah, probably
-20:08 < _robbat21irssi> s3, s3website, swift, swith_auth, swift_website
-*/
-  map<string, list<string> > api_hostname_map;
-  map<string, list<string> > api_endpoints_map;
-
-  string realm_id;
-
-  RGWZoneGroup(): is_master(false){}
-  RGWZoneGroup(const std::string &id, const std::string &name):RGWSystemMetaObj(id, name) {}
-  explicit RGWZoneGroup(const std::string &_name):RGWSystemMetaObj(_name) {}
-  RGWZoneGroup(const std::string &_name, bool _is_master, CephContext *cct, RGWRados* store,
-              const string& _realm_id, const list<string>& _endpoints)
-    : RGWSystemMetaObj(_name, cct , store), endpoints(_endpoints), is_master(_is_master),
-      realm_id(_realm_id) {}
-
-  bool is_master_zonegroup() const { return is_master;}
-  void update_master(bool _is_master) {
-    is_master = _is_master;
-    post_process_params();
-  }
-  void post_process_params();
-
-  void encode(bufferlist& bl) const override {
-    ENCODE_START(4, 1, bl);
-    encode(name, bl);
-    encode(api_name, bl);
-    encode(is_master, bl);
-    encode(endpoints, bl);
-    encode(master_zone, bl);
-    encode(zones, bl);
-    encode(placement_targets, bl);
-    encode(default_placement, bl);
-    encode(hostnames, bl);
-    encode(hostnames_s3website, bl);
-    RGWSystemMetaObj::encode(bl);
-    encode(realm_id, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) override {
-    DECODE_START(4, bl);
-    decode(name, bl);
-    decode(api_name, bl);
-    decode(is_master, bl);
-    decode(endpoints, bl);
-    decode(master_zone, bl);
-    decode(zones, bl);
-    decode(placement_targets, bl);
-    decode(default_placement, bl);
-    if (struct_v >= 2) {
-      decode(hostnames, bl);
-    }
-    if (struct_v >= 3) {
-      decode(hostnames_s3website, bl);
-    }
-    if (struct_v >= 4) {
-      RGWSystemMetaObj::decode(bl);
-      decode(realm_id, bl);
-    } else {
-      id = name;
-    }
-    DECODE_FINISH(bl);
-  }
-
-  int read_default_id(string& default_id, bool old_format = false) override;
-  int set_as_default(bool exclusive = false) override;
-  int create_default(bool old_format = false);
-  int equals(const string& other_zonegroup) const;
-  int add_zone(const RGWZoneParams& zone_params, bool *is_master, bool *read_only,
-               const list<string>& endpoints, const string *ptier_type,
-               bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm,
-               string *predirect_zone);
-  int remove_zone(const std::string& zone_id);
-  int rename_zone(const RGWZoneParams& zone_params);
-  rgw_pool get_pool(CephContext *cct) override;
-  const string get_default_oid(bool old_region_format = false) override;
-  const string& get_info_oid_prefix(bool old_region_format = false) override;
-  const string& get_names_oid_prefix() override;
-  const string& get_predefined_name(CephContext *cct) override;
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-  static void generate_test_instances(list<RGWZoneGroup*>& o);
-};
-WRITE_CLASS_ENCODER(RGWZoneGroup)
-
-struct RGWPeriodMap
-{
-  string id;
-  map<string, RGWZoneGroup> zonegroups;
-  map<string, RGWZoneGroup> zonegroups_by_api;
-  map<string, uint32_t> short_zone_ids;
-
-  string master_zonegroup;
-
-  void encode(bufferlist& bl) const;
-  void decode(bufferlist::const_iterator& bl);
-
-  int update(const RGWZoneGroup& zonegroup, CephContext *cct);
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-
-  void reset() {
-    zonegroups.clear();
-    zonegroups_by_api.clear();
-    master_zonegroup.clear();
-  }
-
-  uint32_t get_zone_short_id(const string& zone_id) const;
-};
-WRITE_CLASS_ENCODER(RGWPeriodMap)
-
-struct RGWPeriodConfig
-{
-  RGWQuotaInfo bucket_quota;
-  RGWQuotaInfo user_quota;
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    encode(bucket_quota, bl);
-    encode(user_quota, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
-    decode(bucket_quota, bl);
-    decode(user_quota, bl);
-    DECODE_FINISH(bl);
-  }
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-
-  // the period config must be stored in a local object outside of the period,
-  // so that it can be used in a default configuration where no realm/period
-  // exists
-  int read(RGWRados *store, const std::string& realm_id);
-  int write(RGWRados *store, const std::string& realm_id);
-
-  static std::string get_oid(const std::string& realm_id);
-  static rgw_pool get_pool(CephContext *cct);
-};
-WRITE_CLASS_ENCODER(RGWPeriodConfig)
-
-/* for backward comaptability */
-struct RGWRegionMap {
-
-  map<string, RGWZoneGroup> regions;
-
-  string master_region;
-
-  RGWQuotaInfo bucket_quota;
-  RGWQuotaInfo user_quota;
-
-  void encode(bufferlist& bl) const;
-  void decode(bufferlist::const_iterator& bl);
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWRegionMap)
-
-struct RGWZoneGroupMap {
-
-  map<string, RGWZoneGroup> zonegroups;
-  map<string, RGWZoneGroup> zonegroups_by_api;
-
-  string master_zonegroup;
-
-  RGWQuotaInfo bucket_quota;
-  RGWQuotaInfo user_quota;
-
-  /* construct the map */
-  int read(CephContext *cct, RGWRados *store);
-
-  void encode(bufferlist& bl) const;
-  void decode(bufferlist::const_iterator& bl);
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWZoneGroupMap)
-
-class RGWRealm;
-
-struct objexp_hint_entry {
-  string tenant;
-  string bucket_name;
-  string bucket_id;
-  rgw_obj_key obj_key;
-  ceph::real_time exp_time;
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(2, 1, bl);
-    encode(bucket_name, bl);
-    encode(bucket_id, bl);
-    encode(obj_key, bl);
-    encode(exp_time, bl);
-    encode(tenant, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    // XXX Do we want DECODE_START_LEGACY_COMPAT_LEN(2, 1, 1, bl); ?
-    DECODE_START(2, bl);
-    decode(bucket_name, bl);
-    decode(bucket_id, bl);
-    decode(obj_key, bl);
-    decode(exp_time, bl);
-    if (struct_v >= 2) {
-      decode(tenant, bl);
-    } else {
-      tenant.clear();
-    }
-    DECODE_FINISH(bl);
-  }
-};
-WRITE_CLASS_ENCODER(objexp_hint_entry)
-
-class RGWPeriod;
-
-class RGWRealm : public RGWSystemMetaObj
-{
-  string current_period;
-  epoch_t epoch{0}; //< realm epoch, incremented for each new period
-
-  int create_control(bool exclusive);
-  int delete_control();
-public:
-  RGWRealm() {}
-  RGWRealm(const string& _id, const string& _name = "") : RGWSystemMetaObj(_id, _name) {}
-  RGWRealm(CephContext *_cct, RGWRados *_store): RGWSystemMetaObj(_cct, _store) {}
-  RGWRealm(const string& _name, CephContext *_cct, RGWRados *_store): RGWSystemMetaObj(_name, _cct, _store){}
-
-  void encode(bufferlist& bl) const override {
-    ENCODE_START(1, 1, bl);
-    RGWSystemMetaObj::encode(bl);
-    encode(current_period, bl);
-    encode(epoch, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) override {
-    DECODE_START(1, bl);
-    RGWSystemMetaObj::decode(bl);
-    decode(current_period, bl);
-    decode(epoch, bl);
-    DECODE_FINISH(bl);
-  }
-
-  int create(bool exclusive = true) override;
-  int delete_obj();
-  rgw_pool get_pool(CephContext *cct) override;
-  const string get_default_oid(bool old_format = false) override;
-  const string& get_names_oid_prefix() override;
-  const string& get_info_oid_prefix(bool old_format = false) override;
-  const string& get_predefined_name(CephContext *cct) override;
-
-  using RGWSystemMetaObj::read_id; // expose as public for radosgw-admin
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-
-  const string& get_current_period() const {
-    return current_period;
-  }
-  int set_current_period(RGWPeriod& period);
-  void clear_current_period_and_epoch() {
-    current_period.clear();
-    epoch = 0;
-  }
-  epoch_t get_epoch() const { return epoch; }
-
-  string get_control_oid();
-  /// send a notify on the realm control object
-  int notify_zone(bufferlist& bl);
-  /// notify the zone of a new period
-  int notify_new_period(const RGWPeriod& period);
-};
-WRITE_CLASS_ENCODER(RGWRealm)
-
-struct RGWPeriodLatestEpochInfo {
-  epoch_t epoch;
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    encode(epoch, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
-    decode(epoch, bl);
-    DECODE_FINISH(bl);
-  }
-
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-};
-WRITE_CLASS_ENCODER(RGWPeriodLatestEpochInfo)
-
-class RGWPeriod
-{
-  string id;
-  epoch_t epoch;
-  string predecessor_uuid;
-  std::vector<std::string> sync_status;
-  RGWPeriodMap period_map;
-  RGWPeriodConfig period_config;
-  string master_zonegroup;
-  string master_zone;
-
-  string realm_id;
-  string realm_name;
-  epoch_t realm_epoch{1}; //< realm epoch when period was made current
-
-  CephContext *cct;
-  RGWRados *store;
-
-  int read_info();
-  int read_latest_epoch(RGWPeriodLatestEpochInfo& epoch_info,
-                        RGWObjVersionTracker *objv = nullptr);
-  int use_latest_epoch();
-  int use_current_period();
-
-  const string get_period_oid();
-  const string get_period_oid_prefix();
-
-  // gather the metadata sync status for each shard; only for use on master zone
-  int update_sync_status(const RGWPeriod &current_period,
-                         std::ostream& error_stream, bool force_if_stale);
-
-public:
-  RGWPeriod() : epoch(0), cct(NULL), store(NULL) {}
-
-  RGWPeriod(const string& period_id, epoch_t _epoch = 0)
-    : id(period_id), epoch(_epoch),
-      cct(NULL), store(NULL) {}
-
-  const string& get_id() const { return id; }
-  epoch_t get_epoch() const { return epoch; }
-  epoch_t get_realm_epoch() const { return realm_epoch; }
-  const string& get_predecessor() const { return predecessor_uuid; }
-  const string& get_master_zone() const { return master_zone; }
-  const string& get_master_zonegroup() const { return master_zonegroup; }
-  const string& get_realm() const { return realm_id; }
-  const RGWPeriodMap& get_map() const { return period_map; }
-  RGWPeriodConfig& get_config() { return period_config; }
-  const RGWPeriodConfig& get_config() const { return period_config; }
-  const std::vector<std::string>& get_sync_status() const { return sync_status; }
-  rgw_pool get_pool(CephContext *cct);
-  const string& get_latest_epoch_oid();
-  const string& get_info_oid_prefix();
-
-  void set_user_quota(RGWQuotaInfo& user_quota) {
-    period_config.user_quota = user_quota;
-  }
-
-  void set_bucket_quota(RGWQuotaInfo& bucket_quota) {
-    period_config.bucket_quota = bucket_quota;
-  }
-
-  void set_id(const string& id) {
-    this->id = id;
-    period_map.id = id;
-  }
-  void set_epoch(epoch_t epoch) { this->epoch = epoch; }
-  void set_realm_epoch(epoch_t epoch) { realm_epoch = epoch; }
-
-  void set_predecessor(const string& predecessor)
-  {
-    predecessor_uuid = predecessor;
-  }
-
-  void set_realm_id(const string& _realm_id) {
-    realm_id = _realm_id;
-  }
-
-  int reflect();
-
-  int get_zonegroup(RGWZoneGroup& zonegroup,
-                   const string& zonegroup_id);
-
-  bool is_single_zonegroup() const
-  {
-      return (period_map.zonegroups.size() == 1);
-  }
-
-  /*
-    returns true if there are several zone groups with a least one zone
-   */
-  bool is_multi_zonegroups_with_zones()
-  {
-    int count = 0;
-    for (const auto& zg:  period_map.zonegroups) {
-      if (zg.second.zones.size() > 0) {
-       if (count++ > 0) {
-         return true;
-       }
-      }
-    }
-    return false;
-  }
-
-  int get_latest_epoch(epoch_t& epoch);
-  int set_latest_epoch(epoch_t epoch, bool exclusive = false,
-                       RGWObjVersionTracker *objv = nullptr);
-  // update latest_epoch if the given epoch is higher, else return -EEXIST
-  int update_latest_epoch(epoch_t epoch);
-
-  int init(CephContext *_cct, RGWRados *_store, const string &period_realm_id, const string &period_realm_name = "",
-          bool setup_obj = true);
-  int init(CephContext *_cct, RGWRados *_store, bool setup_obj = true);  
-
-  int create(bool exclusive = true);
-  int delete_obj();
-  int store_info(bool exclusive);
-  int add_zonegroup(const RGWZoneGroup& zonegroup);
-
-  void fork();
-  int update();
-
-  // commit a staging period; only for use on master zone
-  int commit(RGWRealm& realm, const RGWPeriod &current_period,
-             std::ostream& error_stream, bool force_if_stale = false);
-
-  void encode(bufferlist& bl) const {
-    ENCODE_START(1, 1, bl);
-    encode(id, bl);
-    encode(epoch, bl);
-    encode(realm_epoch, bl);
-    encode(predecessor_uuid, bl);
-    encode(sync_status, bl);
-    encode(period_map, bl);
-    encode(master_zone, bl);
-    encode(master_zonegroup, bl);
-    encode(period_config, bl);
-    encode(realm_id, bl);
-    encode(realm_name, bl);
-    ENCODE_FINISH(bl);
-  }
-
-  void decode(bufferlist::const_iterator& bl) {
-    DECODE_START(1, bl);
-    decode(id, bl);
-    decode(epoch, bl);
-    decode(realm_epoch, bl);
-    decode(predecessor_uuid, bl);
-    decode(sync_status, bl);
-    decode(period_map, bl);
-    decode(master_zone, bl);
-    decode(master_zonegroup, bl);
-    decode(period_config, bl);
-    decode(realm_id, bl);
-    decode(realm_name, bl);
-    DECODE_FINISH(bl);
-  }
-  void dump(Formatter *f) const;
-  void decode_json(JSONObj *obj);
-
-  static string get_staging_id(const string& realm_id) {
-    return realm_id + ":staging";
-  }
-};
-WRITE_CLASS_ENCODER(RGWPeriod)
-
 class RGWDataChangesLog;
 class RGWMetaSyncStatusManager;
 class RGWDataSyncStatusManager;
@@ -2261,12 +1328,8 @@ protected:
   RGWSyncModuleInstanceRef sync_module;
   bool writeable_zone{false};
 
-  RGWZoneGroup zonegroup;
-  RGWZone zone_public_config; /* external zone params, e.g., entrypoints, log flags, etc. */  
-  RGWZoneParams zone_params; /* internal zone params, e.g., rados pools */
-  uint32_t zone_short_id;
 
-  RGWPeriod current_period;
+  std::shared_ptr<RGWSI_Zone> zone_svc;
 
   RGWIndexCompletionManager *index_completion_manager{nullptr};
 public:
@@ -2287,7 +1350,6 @@ public:
                quota_handler(NULL),
                finisher(NULL),
                cr_registry(NULL),
-               zone_short_id(0),
                rest_master_conn(NULL),
                meta_mgr(NULL), data_log(NULL), reshard(NULL) {}
 
@@ -2356,40 +1418,6 @@ public:
     return true;
   }
 
-  int get_zonegroup(const string& id, RGWZoneGroup& zonegroup) {
-    int ret = 0;
-    if (id == get_zonegroup().get_id()) {
-      zonegroup = get_zonegroup();
-    } else if (!current_period.get_id().empty()) {
-      ret = current_period.get_zonegroup(zonegroup, id);
-    }
-    return ret;
-  }
-
-  RGWRealm& get_realm() {
-    return realm;
-  }
-
-  RGWZoneParams& get_zone_params() { return zone_params; }
-  RGWZoneGroup& get_zonegroup() {
-    return zonegroup;
-  }
-  RGWZone& get_zone() {
-    return zone_public_config;
-  }
-
-  bool zone_is_writeable() {
-    return writeable_zone && !get_zone().is_read_only();
-  }
-
-  uint32_t get_zone_short_id() const {
-    return zone_short_id;
-  }
-
-  bool zone_syncs_from(RGWZone& target_zone, RGWZone& source_zone);
-
-  bool get_redirect_zone_endpoint(string *endpoint);
-
   const RGWQuotaInfo& get_bucket_quota() {
     return current_period.get_config().bucket_quota;
   }
@@ -3572,12 +2600,7 @@ public:
   int add_bucket_to_reshard(const RGWBucketInfo& bucket_info, uint32_t new_num_shards);
 
   uint64_t instance_id();
-  const string& zone_name() {
-    return get_zone_params().get_name();
-  }
-  const string& zone_id() {
-    return get_zone_params().get_id();
-  }
+
   string unique_id(uint64_t unique_num) {
     char buf[32];
     snprintf(buf, sizeof(buf), ".%llu.%llu", (unsigned long long)instance_id(), (unsigned long long)unique_num);
index 04022b35845370ea6745a0b8449ae2f4b67e8e8d..f77a14e949e08b23f157e37f5f6f0509b257f5b1 100644 (file)
@@ -35,7 +35,6 @@ public:
   const std::string& type() {
     return svc_type;
   }
-  virtual std::vector<std::string> deps() = 0;
   virtual int create_instance(JSONFormattable& conf, RGWServiceInstanceRef *instance) = 0;
 };
 
@@ -52,11 +51,14 @@ protected:
   string svc_instance;
   uint64_t svc_id{0};
 
+  virtual std::vector<std::string> get_deps() {
+    return vector<std::string>();
+  }
+  virtual int init(JSONFormattable& conf) = 0;
 public:
   RGWServiceInstance(RGWService *svc, CephContext *_cct) : cct(_cct) {}
 
   virtual ~RGWServiceInstance();
-  virtual int init(JSONFormattable& conf) = 0;
 
   string get_title() {
     return svc->type() + ":" + svc_instance;
diff --git a/src/rgw/rgw_zone.cc b/src/rgw/rgw_zone.cc
new file mode 100644 (file)
index 0000000..ce2e956
--- /dev/null
@@ -0,0 +1,1848 @@
+#include "rgw_zone.h"
+
+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);
+  }
+}
+
+rgw_pool RGWZoneGroup::get_pool(CephContext *cct_)
+{
+  if (cct_->_conf->rgw_zonegroup_root_pool.empty()) {
+    return rgw_pool(RGW_DEFAULT_ZONEGROUP_ROOT_POOL);
+  }
+
+  return rgw_pool(cct_->_conf->rgw_zonegroup_root_pool);
+}
+
+int RGWZoneGroup::create_default(bool old_format)
+{
+  name = default_zonegroup_name;
+  api_name = default_zonegroup_name;
+  is_master = true;
+
+  RGWZoneGroupPlacementTarget placement_target;
+  placement_target.name = "default-placement";
+  placement_targets[placement_target.name] = placement_target;
+  default_placement = "default-placement";
+
+  RGWZoneParams zone_params(default_zone_name);
+
+  int r = zone_params.init(cct, store, false);
+  if (r < 0) {
+    ldout(cct, 0) << "create_default: error initializing zone params: " << cpp_strerror(-r) << dendl;
+    return r;
+  }
+
+  r = zone_params.create_default();
+  if (r < 0 && r != -EEXIST) {
+    ldout(cct, 0) << "create_default: error in create_default  zone params: " << cpp_strerror(-r) << dendl;
+    return r;
+  } else if (r == -EEXIST) {
+    ldout(cct, 10) << "zone_params::create_default() returned -EEXIST, we raced with another default zone_params creation" << dendl;
+    zone_params.clear_id();
+    r = zone_params.init(cct, store);
+    if (r < 0) {
+      ldout(cct, 0) << "create_default: error in init existing zone params: " << cpp_strerror(-r) << dendl;
+      return r;
+    }
+    ldout(cct, 20) << "zone_params::create_default() " << zone_params.get_name() << " id " << zone_params.get_id()
+                  << dendl;
+  }
+  
+  RGWZone& default_zone = zones[zone_params.get_id()];
+  default_zone.name = zone_params.get_name();
+  default_zone.id = zone_params.get_id();
+  master_zone = default_zone.id;
+  
+  r = create();
+  if (r < 0 && r != -EEXIST) {
+    ldout(cct, 0) << "error storing zone group info: " << cpp_strerror(-r) << dendl;
+    return r;
+  }
+
+  if (r == -EEXIST) {
+    ldout(cct, 10) << "create_default() returned -EEXIST, we raced with another zonegroup creation" << dendl;
+    id.clear();
+    r = init(cct, store);
+    if (r < 0) {
+      return r;
+    }
+  }
+
+  if (old_format) {
+    name = id;
+  }
+
+  post_process_params();
+
+  return 0;
+}
+
+const string RGWZoneGroup::get_default_oid(bool old_region_format)
+{
+  if (old_region_format) {
+    if (cct->_conf->rgw_default_region_info_oid.empty()) {
+      return default_region_info_oid;
+    }
+    return cct->_conf->rgw_default_region_info_oid;
+  }
+
+  string default_oid = cct->_conf->rgw_default_zonegroup_info_oid;
+
+  if (cct->_conf->rgw_default_zonegroup_info_oid.empty()) {
+    default_oid = default_zone_group_info_oid;
+  }
+
+  default_oid += "." + realm_id;
+
+  return default_oid;
+}
+
+const string& RGWZoneGroup::get_info_oid_prefix(bool old_region_format)
+{
+  if (old_region_format) {
+    return region_info_oid_prefix;
+  }
+  return zone_group_info_oid_prefix;
+}
+
+const string& RGWZoneGroup::get_names_oid_prefix()
+{
+  return zonegroup_names_oid_prefix;
+}
+
+const string& RGWZoneGroup::get_predefined_name(CephContext *cct) {
+  return cct->_conf->rgw_zonegroup;
+}
+
+int RGWZoneGroup::equals(const string& other_zonegroup) const
+{
+  if (is_master && other_zonegroup.empty())
+    return true;
+
+  return (id  == other_zonegroup);
+}
+
+int RGWZoneGroup::add_zone(const RGWZoneParams& zone_params, bool *is_master, bool *read_only,
+                           const list<string>& endpoints, const string *ptier_type,
+                           bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm,
+                           string *predirect_zone)
+{
+  auto& zone_id = zone_params.get_id();
+  auto& zone_name = zone_params.get_name();
+
+  // check for duplicate zone name on insert
+  if (!zones.count(zone_id)) {
+    for (const auto& zone : zones) {
+      if (zone.second.name == zone_name) {
+        ldout(cct, 0) << "ERROR: found existing zone name " << zone_name
+            << " (" << zone.first << ") in zonegroup " << get_name() << dendl;
+        return -EEXIST;
+      }
+    }
+  }
+
+  if (is_master) {
+    if (*is_master) {
+      if (!master_zone.empty() && master_zone != zone_id) {
+        ldout(cct, 0) << "NOTICE: overriding master zone: " << master_zone << dendl;
+      }
+      master_zone = zone_id;
+    } else if (master_zone == zone_id) {
+      master_zone.clear();
+    }
+  }
+
+  RGWZone& zone = zones[zone_id];
+  zone.name = zone_name;
+  zone.id = zone_id;
+  if (!endpoints.empty()) {
+    zone.endpoints = endpoints;
+  }
+  if (read_only) {
+    zone.read_only = *read_only;
+  }
+  if (ptier_type) {
+    zone.tier_type = *ptier_type;
+    if (!store->get_sync_modules_manager()->get_module(*ptier_type, nullptr)) {
+      ldout(cct, 0) << "ERROR: could not found sync module: " << *ptier_type 
+                    << ",  valid sync modules: " 
+                    << store->get_sync_modules_manager()->get_registered_module_names()
+                    << dendl;
+      return -ENOENT;
+    }
+  }
+
+  if (psync_from_all) {
+    zone.sync_from_all = *psync_from_all;
+  }
+
+  if (predirect_zone) {
+    zone.redirect_zone = *predirect_zone;
+  }
+
+  for (auto add : sync_from) {
+    zone.sync_from.insert(add);
+  }
+
+  for (auto rm : sync_from_rm) {
+    zone.sync_from.erase(rm);
+  }
+
+  post_process_params();
+
+  return update();
+}
+
+
+int RGWZoneGroup::rename_zone(const RGWZoneParams& zone_params)
+{ 
+  RGWZone& zone = zones[zone_params.get_id()];
+  zone.name = zone_params.get_name();
+  
+  return update();
+}
+
+void RGWZoneGroup::post_process_params()
+{
+  bool log_data = zones.size() > 1;
+
+  if (master_zone.empty()) {
+    map<string, RGWZone>::iterator iter = zones.begin();
+    if (iter != zones.end()) {
+      master_zone = iter->first;
+    }
+  }
+  
+  for (map<string, RGWZone>::iterator iter = zones.begin(); iter != zones.end(); ++iter) {
+    RGWZone& zone = iter->second;
+    zone.log_data = log_data;
+
+    RGWZoneParams zone_params(zone.id, zone.name);
+    int ret = zone_params.init(cct, store);
+    if (ret < 0) {
+      ldout(cct, 0) << "WARNING: could not read zone params for zone id=" << zone.id << " name=" << zone.name << dendl;
+      continue;
+    }
+
+    for (map<string, RGWZonePlacementInfo>::iterator iter = zone_params.placement_pools.begin(); 
+         iter != zone_params.placement_pools.end(); ++iter) {
+      const string& placement_name = iter->first;
+      if (placement_targets.find(placement_name) == placement_targets.end()) {
+        RGWZoneGroupPlacementTarget placement_target;
+        placement_target.name = placement_name;
+        placement_targets[placement_name] = placement_target;
+      }
+    }
+  }
+
+  if (default_placement.empty() && !placement_targets.empty()) {
+    default_placement = placement_targets.begin()->first;
+  }
+}
+
+int RGWZoneGroup::remove_zone(const std::string& zone_id)
+{
+  map<string, RGWZone>::iterator iter = zones.find(zone_id);
+  if (iter == zones.end()) {
+    ldout(cct, 0) << "zone id " << zone_id << " is not a part of zonegroup "
+        << name << dendl;
+    return -ENOENT;
+  }
+
+  zones.erase(iter);
+
+  post_process_params();
+
+  return update();
+}
+
+int RGWZoneGroup::read_default_id(string& default_id, bool old_format)
+{
+  if (realm_id.empty()) {
+    /* try using default realm */
+    RGWRealm realm;
+    int ret = realm.init(cct, store);
+    // no default realm exist
+    if (ret < 0) {
+      return read_id(default_zonegroup_name, default_id);
+    }
+    realm_id = realm.get_id();
+  }
+
+  return RGWSystemMetaObj::read_default_id(default_id, old_format);
+}
+
+int RGWZoneGroup::set_as_default(bool exclusive)
+{
+  if (realm_id.empty()) {
+    /* try using default realm */
+    RGWRealm realm;
+    int ret = realm.init(cct, store);
+    if (ret < 0) {
+      ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
+      return -EINVAL;
+    }
+    realm_id = realm.get_id();
+  }
+
+  return RGWSystemMetaObj::set_as_default(exclusive);
+}
+
+int RGWSystemMetaObj::init(CephContext *_cct, RGWRados *_store, bool setup_obj, bool old_format)
+{
+  cct = _cct;
+  store = _store;
+
+  if (!setup_obj)
+    return 0;
+
+  if (old_format && id.empty()) {
+    id = name;
+  }
+
+  if (id.empty()) {
+    int r;
+    if (name.empty()) {
+      name = get_predefined_name(cct);
+    }
+    if (name.empty()) {
+      r = use_default(old_format);
+      if (r < 0) {
+       return r;
+      }
+    } else if (!old_format) {
+      r = read_id(name, id);
+      if (r < 0) {
+        if (r != -ENOENT) {
+          ldout(cct, 0) << "error in read_id for object name: " << name << " : " << cpp_strerror(-r) << dendl;
+        }
+        return r;
+      }
+    }
+  }
+
+  return read_info(id, old_format);
+}
+
+int RGWSystemMetaObj::read_default(RGWDefaultSystemMetaObjInfo& default_info, const string& oid)
+{
+  using ceph::decode;
+  auto pool = get_pool(cct);
+  bufferlist bl;
+  RGWObjectCtx obj_ctx(store);
+  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
+  if (ret < 0)
+    return ret;
+
+  try {
+    auto iter = bl.cbegin();
+    decode(default_info, iter);
+  } catch (buffer::error& err) {
+    ldout(cct, 0) << "error decoding data from " << pool << ":" << oid << dendl;
+    return -EIO;
+  }
+
+  return 0;
+}
+
+int RGWSystemMetaObj::read_default_id(string& default_id, bool old_format)
+{
+  RGWDefaultSystemMetaObjInfo default_info;
+
+  int ret = read_default(default_info, get_default_oid(old_format));
+  if (ret < 0) {
+    return ret;
+  }
+
+  default_id = default_info.default_id;
+
+  return 0;
+}
+
+int RGWSystemMetaObj::use_default(bool old_format)
+{
+  return read_default_id(id, old_format);
+}
+
+int RGWSystemMetaObj::set_as_default(bool exclusive)
+{
+  using ceph::encode;
+  string oid  = get_default_oid();
+
+  rgw_pool pool(get_pool(cct));
+  bufferlist bl;
+
+  RGWDefaultSystemMetaObjInfo default_info;
+  default_info.default_id = id;
+
+  encode(default_info, bl);
+
+  int ret = rgw_put_system_obj(store, pool, oid, bl,
+                               exclusive, NULL, real_time(), NULL);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
+int RGWSystemMetaObj::read_id(const string& obj_name, string& object_id)
+{
+  using ceph::decode;
+  rgw_pool pool(get_pool(cct));
+  bufferlist bl;
+
+  string oid = get_names_oid_prefix() + obj_name;
+
+  RGWObjectCtx obj_ctx(store);
+  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
+  if (ret < 0) {
+    return ret;
+  }
+
+  RGWNameToId nameToId;
+  try {
+    auto iter = bl.cbegin();
+    decode(nameToId, iter);
+  } catch (buffer::error& err) {
+    ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
+    return -EIO;
+  }
+  object_id = nameToId.obj_id;
+  return 0;
+}
+
+int RGWSystemMetaObj::delete_obj(bool old_format)
+{
+  rgw_pool pool(get_pool(cct));
+
+  /* check to see if obj is the default */
+  RGWDefaultSystemMetaObjInfo default_info;
+  int ret = read_default(default_info, get_default_oid(old_format));
+  if (ret < 0 && ret != -ENOENT)
+    return ret;
+  if (default_info.default_id == id || (old_format && default_info.default_id == name)) {
+    string oid = get_default_oid(old_format);
+    rgw_raw_obj default_named_obj(pool, oid);
+    ret = store->delete_system_obj(default_named_obj);
+    if (ret < 0) {
+      ldout(cct, 0) << "Error delete default obj name  " << name << ": " << cpp_strerror(-ret) << dendl;
+      return ret;
+    }
+  }
+  if (!old_format) {
+    string oid  = get_names_oid_prefix() + name;
+    rgw_raw_obj object_name(pool, oid);
+    ret = store->delete_system_obj(object_name);
+    if (ret < 0) {
+      ldout(cct, 0) << "Error delete obj name  " << name << ": " << cpp_strerror(-ret) << dendl;
+      return ret;
+    }
+  }
+
+  string oid = get_info_oid_prefix(old_format);
+  if (old_format) {
+    oid += name;
+  } else {
+    oid += id;
+  }
+
+  rgw_raw_obj object_id(pool, oid);
+  ret = store->delete_system_obj(object_id);
+  if (ret < 0) {
+    ldout(cct, 0) << "Error delete object id " << id << ": " << cpp_strerror(-ret) << dendl;
+  }
+
+  return ret;
+}
+
+int RGWSystemMetaObj::store_name(bool exclusive)
+{
+  rgw_pool pool(get_pool(cct));
+  string oid = get_names_oid_prefix() + name;
+
+  RGWNameToId nameToId;
+  nameToId.obj_id = id;
+
+  bufferlist bl;
+  using ceph::encode;
+  encode(nameToId, bl);
+  return rgw_put_system_obj(store, pool, oid, bl, exclusive, NULL, real_time(), NULL);
+}
+
+int RGWSystemMetaObj::rename(const string& new_name)
+{
+  string new_id;
+  int ret = read_id(new_name, new_id);
+  if (!ret) {
+    return -EEXIST;
+  }
+  if (ret < 0 && ret != -ENOENT) {
+    ldout(cct, 0) << "Error read_id " << new_name << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+  string old_name = name;
+  name = new_name;
+  ret = update();
+  if (ret < 0) {
+    ldout(cct, 0) << "Error storing new obj info " << new_name << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+  ret = store_name(true);
+  if (ret < 0) {
+    ldout(cct, 0) << "Error storing new name " << new_name << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+  /* delete old name */
+  rgw_pool pool(get_pool(cct));
+  string oid = get_names_oid_prefix() + old_name;
+  rgw_raw_obj old_name_obj(pool, oid);
+  ret = store->delete_system_obj(old_name_obj);
+  if (ret < 0) {
+    ldout(cct, 0) << "Error delete old obj name  " << old_name << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  return ret;
+}
+
+int RGWSystemMetaObj::read_info(const string& obj_id, bool old_format)
+{
+  rgw_pool pool(get_pool(cct));
+
+  bufferlist bl;
+
+  string oid = get_info_oid_prefix(old_format) + obj_id;
+
+  RGWObjectCtx obj_ctx(store);
+  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
+  if (ret < 0) {
+    ldout(cct, 0) << "failed reading obj info from " << pool << ":" << oid << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+  using ceph::decode;
+
+  try {
+    auto iter = bl.cbegin();
+    decode(*this, iter);
+  } catch (buffer::error& err) {
+    ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << oid << dendl;
+    return -EIO;
+  }
+
+  return 0;
+}
+
+int RGWSystemMetaObj::read()
+{
+  int ret = read_id(name, id);
+  if (ret < 0) {
+    return ret;
+  }
+
+  return read_info(id);
+}
+
+int RGWSystemMetaObj::create(bool exclusive)
+{
+  int ret;
+  
+  /* check to see the name is not used */
+  ret = read_id(name, id);
+  if (exclusive && ret == 0) {
+    ldout(cct, 10) << "ERROR: name " << name << " already in use for obj id " << id << dendl;
+    return -EEXIST;
+  } else if ( ret < 0 && ret != -ENOENT) {
+    ldout(cct, 0) << "failed reading obj id  " << id << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  if (id.empty()) {
+    /* create unique id */
+    uuid_d new_uuid;
+    char uuid_str[37];
+    new_uuid.generate_random();
+    new_uuid.print(uuid_str);
+    id = uuid_str;
+  }
+
+  ret = store_info(exclusive);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR:  storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  return store_name(exclusive);
+}
+
+int RGWSystemMetaObj::store_info(bool exclusive)
+{
+  rgw_pool pool(get_pool(cct));
+
+  string oid = get_info_oid_prefix() + id;
+
+  bufferlist bl;
+  using ceph::encode;
+  encode(*this, bl);
+  return rgw_put_system_obj(store, pool, oid, bl, exclusive, NULL, real_time(), NULL);
+}
+
+int RGWSystemMetaObj::write(bool exclusive)
+{
+  int ret = store_info(exclusive);
+  if (ret < 0) {
+    ldout(cct, 20) << __func__ << "(): store_info() returned ret=" << ret << dendl;
+    return ret;
+  }
+  ret = store_name(exclusive);
+  if (ret < 0) {
+    ldout(cct, 20) << __func__ << "(): store_name() returned ret=" << ret << dendl;
+    return ret;
+  }
+  return 0;
+}
+
+
+const string& RGWRealm::get_predefined_name(CephContext *cct) {
+  return cct->_conf->rgw_realm;
+}
+
+int RGWRealm::create(bool exclusive)
+{
+  int ret = RGWSystemMetaObj::create(exclusive);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR creating new realm object " << name << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+  // create the control object for watch/notify
+  ret = create_control(exclusive);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR creating control for new realm " << name << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+  RGWPeriod period;
+  if (current_period.empty()) {
+    /* create new period for the realm */
+    ret = period.init(cct, store, id, name, false);
+    if (ret < 0 ) {
+      return ret;
+    }
+    ret = period.create(true);
+    if (ret < 0) {
+      ldout(cct, 0) << "ERROR: creating new period for realm " << name << ": " << cpp_strerror(-ret) << dendl;
+      return ret;
+    }
+  } else {
+    period = RGWPeriod(current_period, 0);
+    int ret = period.init(cct, store, id, name);
+    if (ret < 0) {
+      ldout(cct, 0) << "ERROR: failed to init period " << current_period << dendl;
+      return ret;
+    }
+  }
+  ret = set_current_period(period);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR: failed set current period " << current_period << dendl;
+    return ret;
+  }
+  // try to set as default. may race with another create, so pass exclusive=true
+  // so we don't override an existing default
+  ret = set_as_default(true);
+  if (ret < 0 && ret != -EEXIST) {
+    ldout(cct, 0) << "WARNING: failed to set realm as default realm, ret=" << ret << dendl;
+  }
+
+  return 0;
+}
+
+int RGWRealm::delete_obj()
+{
+  int ret = RGWSystemMetaObj::delete_obj();
+  if (ret < 0) {
+    return ret;
+  }
+  return delete_control();
+}
+
+int RGWRealm::create_control(bool exclusive)
+{
+  auto pool = rgw_pool{get_pool(cct)};
+  auto oid = get_control_oid();
+  bufferlist bl;
+  return rgw_put_system_obj(store, pool, oid, bl, exclusive,
+                            nullptr, real_time(), nullptr);
+}
+
+int RGWRealm::delete_control()
+{
+  auto pool = rgw_pool{get_pool(cct)};
+  auto obj = rgw_raw_obj{pool, get_control_oid()};
+  return store->delete_system_obj(obj);
+}
+
+rgw_pool RGWRealm::get_pool(CephContext *cct)
+{
+  if (cct->_conf->rgw_realm_root_pool.empty()) {
+    return rgw_pool(RGW_DEFAULT_REALM_ROOT_POOL);
+  }
+  return rgw_pool(cct->_conf->rgw_realm_root_pool);
+}
+
+const string RGWRealm::get_default_oid(bool old_format)
+{
+  if (cct->_conf->rgw_default_realm_info_oid.empty()) {
+    return default_realm_info_oid;
+  }
+  return cct->_conf->rgw_default_realm_info_oid;
+}
+
+const string& RGWRealm::get_names_oid_prefix()
+{
+  return realm_names_oid_prefix;
+}
+
+const string& RGWRealm::get_info_oid_prefix(bool old_format)
+{
+  return realm_info_oid_prefix;
+}
+
+int RGWRealm::set_current_period(RGWPeriod& period)
+{
+  // update realm epoch to match the period's
+  if (epoch > period.get_realm_epoch()) {
+    ldout(cct, 0) << "ERROR: set_current_period with old realm epoch "
+        << period.get_realm_epoch() << ", current epoch=" << epoch << dendl;
+    return -EINVAL;
+  }
+  if (epoch == period.get_realm_epoch() && current_period != period.get_id()) {
+    ldout(cct, 0) << "ERROR: set_current_period with same realm epoch "
+        << period.get_realm_epoch() << ", but different period id "
+        << period.get_id() << " != " << current_period << dendl;
+    return -EINVAL;
+  }
+
+  epoch = period.get_realm_epoch();
+  current_period = period.get_id();
+
+  int ret = update();
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR: period update: " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  ret = period.reflect();
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR: period.reflect(): " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  return 0;
+}
+
+string RGWRealm::get_control_oid()
+{
+  return get_info_oid_prefix() + id + ".control";
+}
+
+int RGWRealm::notify_zone(bufferlist& bl)
+{
+  // open a context on the realm's pool
+  rgw_pool pool{get_pool(cct)};
+  librados::IoCtx ctx;
+  int r = rgw_init_ioctx(store->get_rados_handle(), pool, ctx);
+  if (r < 0) {
+    ldout(cct, 0) << "Failed to open pool " << pool << dendl;
+    return r;
+  }
+  // send a notify on the realm object
+  r = ctx.notify2(get_control_oid(), bl, 0, nullptr);
+  if (r < 0) {
+    ldout(cct, 0) << "Realm notify failed with " << r << dendl;
+    return r;
+  }
+  return 0;
+}
+
+int RGWRealm::notify_new_period(const RGWPeriod& period)
+{
+  bufferlist bl;
+  using ceph::encode;
+  // push the period to dependent zonegroups/zones
+  encode(RGWRealmNotify::ZonesNeedPeriod, bl);
+  encode(period, bl);
+  // reload the gateway with the new period
+  encode(RGWRealmNotify::Reload, bl);
+
+  return notify_zone(bl);
+}
+
+std::string RGWPeriodConfig::get_oid(const std::string& realm_id)
+{
+  if (realm_id.empty()) {
+    return "period_config.default";
+  }
+  return "period_config." + realm_id;
+}
+
+rgw_pool RGWPeriodConfig::get_pool(CephContext *cct)
+{
+  const auto& pool_name = cct->_conf->rgw_period_root_pool;
+  if (pool_name.empty()) {
+    return {RGW_DEFAULT_PERIOD_ROOT_POOL};
+  }
+  return {pool_name};
+}
+
+int RGWPeriodConfig::read(RGWRados *store, const std::string& realm_id)
+{
+  RGWObjectCtx obj_ctx(store);
+  const auto& pool = get_pool(store->ctx());
+  const auto& oid = get_oid(realm_id);
+  bufferlist bl;
+
+  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, nullptr, nullptr);
+  if (ret < 0) {
+    return ret;
+  }
+  using ceph::decode;
+  try {
+    auto iter = bl.cbegin();
+    decode(*this, iter);
+  } catch (buffer::error& err) {
+    return -EIO;
+  }
+  return 0;
+}
+
+int RGWPeriodConfig::write(RGWRados *store, const std::string& realm_id)
+{
+  const auto& pool = get_pool(store->ctx());
+  const auto& oid = get_oid(realm_id);
+  bufferlist bl;
+  using ceph::encode;
+  encode(*this, bl);
+  return rgw_put_system_obj(store, pool, oid, bl,
+                            false, nullptr, real_time(), nullptr);
+}
+
+int RGWPeriod::init(CephContext *_cct, RGWRados *_store, const string& period_realm_id,
+                   const string& period_realm_name, bool setup_obj)
+{
+  cct = _cct;
+  store = _store;
+  realm_id = period_realm_id;
+  realm_name = period_realm_name;
+
+  if (!setup_obj)
+    return 0;
+
+  return init(_cct, _store, setup_obj);
+}
+
+
+int RGWPeriod::init(CephContext *_cct, RGWRados *_store, bool setup_obj)
+{
+  cct = _cct;
+  store = _store;
+
+  if (!setup_obj)
+    return 0;
+
+  if (id.empty()) {
+    RGWRealm realm(realm_id, realm_name);
+    int ret = realm.init(cct, store);
+    if (ret < 0) {
+      ldout(cct, 0) << "RGWPeriod::init failed to init realm " << realm_name  << " id " << realm_id << " : " <<
+       cpp_strerror(-ret) << dendl;
+      return ret;
+    }
+    id = realm.get_current_period();
+    realm_id = realm.get_id();
+  }
+
+  if (!epoch) {
+    int ret = use_latest_epoch();
+    if (ret < 0) {
+      ldout(cct, 0) << "failed to use_latest_epoch period id " << id << " realm " << realm_name  << " id " << realm_id
+          << " : " << cpp_strerror(-ret) << dendl;
+      return ret;
+    }
+  }
+
+  return read_info();
+}
+
+
+int RGWPeriod::get_zonegroup(RGWZoneGroup& zonegroup, const string& zonegroup_id) {
+  map<string, RGWZoneGroup>::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;
+}
+
+bool RGWRados::get_redirect_zone_endpoint(string *endpoint)
+{
+  if (zone_public_config.redirect_zone.empty()) {
+    return false;
+  }
+
+  auto iter = zone_conn_map.find(zone_public_config.redirect_zone);
+  if (iter == zone_conn_map.end()) {
+    ldout(cct, 0) << "ERROR: cannot find entry for redirect zone: " << zone_public_config.redirect_zone << dendl;
+    return false;
+  }
+
+  RGWRESTConn *conn = iter->second;
+
+  int ret = conn->get_url(*endpoint);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR: redirect zone, conn->get_endpoint() returned ret=" << ret << dendl;
+    return false;
+  }
+
+  return true;
+}
+
+const string& RGWPeriod::get_latest_epoch_oid()
+{
+  if (cct->_conf->rgw_period_latest_epoch_info_oid.empty()) {
+    return period_latest_epoch_info_oid;
+  }
+  return cct->_conf->rgw_period_latest_epoch_info_oid;
+}
+
+const string& RGWPeriod::get_info_oid_prefix()
+{
+  return period_info_oid_prefix;
+}
+
+const string RGWPeriod::get_period_oid_prefix()
+{
+  return get_info_oid_prefix() + id;
+}
+
+const string RGWPeriod::get_period_oid()
+{
+  std::ostringstream oss;
+  oss << get_period_oid_prefix();
+  // skip the epoch for the staging period
+  if (id != get_staging_id(realm_id))
+    oss << "." << epoch;
+  return oss.str();
+}
+
+int RGWPeriod::read_latest_epoch(RGWPeriodLatestEpochInfo& info,
+                                 RGWObjVersionTracker *objv)
+{
+  string oid = get_period_oid_prefix() + get_latest_epoch_oid();
+
+  rgw_pool pool(get_pool(cct));
+  bufferlist bl;
+  RGWObjectCtx obj_ctx(store);
+  int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, objv, nullptr);
+  if (ret < 0) {
+    ldout(cct, 1) << "error read_lastest_epoch " << pool << ":" << oid << dendl;
+    return ret;
+  }
+  try {
+    auto iter = bl.cbegin();
+    using ceph::decode;
+    decode(info, iter);
+  } catch (buffer::error& err) {
+    ldout(cct, 0) << "error decoding data from " << pool << ":" << oid << dendl;
+    return -EIO;
+  }
+
+  return 0;
+}
+
+int RGWPeriod::get_latest_epoch(epoch_t& latest_epoch)
+{
+  RGWPeriodLatestEpochInfo info;
+
+  int ret = read_latest_epoch(info);
+  if (ret < 0) {
+    return ret;
+  }
+
+  latest_epoch = info.epoch;
+
+  return 0;
+}
+
+int RGWPeriod::use_latest_epoch()
+{
+  RGWPeriodLatestEpochInfo info;
+  int ret = read_latest_epoch(info);
+  if (ret < 0) {
+    return ret;
+  }
+
+  epoch = info.epoch;
+
+  return 0;
+}
+
+int RGWPeriod::set_latest_epoch(epoch_t epoch, bool exclusive,
+                                RGWObjVersionTracker *objv)
+{
+  string oid = get_period_oid_prefix() + get_latest_epoch_oid();
+
+  rgw_pool pool(get_pool(cct));
+  bufferlist bl;
+
+  RGWPeriodLatestEpochInfo info;
+  info.epoch = epoch;
+
+  using ceph::encode;
+  encode(info, bl);
+
+  return rgw_put_system_obj(store, pool, oid, bl,
+                            exclusive, objv, real_time(), nullptr);
+}
+
+int RGWPeriod::update_latest_epoch(epoch_t epoch)
+{
+  static constexpr int MAX_RETRIES = 20;
+
+  for (int i = 0; i < MAX_RETRIES; i++) {
+    RGWPeriodLatestEpochInfo info;
+    RGWObjVersionTracker objv;
+    bool exclusive = false;
+
+    // read existing epoch
+    int r = read_latest_epoch(info, &objv);
+    if (r == -ENOENT) {
+      // use an exclusive create to set the epoch atomically
+      exclusive = true;
+      ldout(cct, 20) << "creating initial latest_epoch=" << epoch
+          << " for period=" << id << dendl;
+    } else if (r < 0) {
+      ldout(cct, 0) << "ERROR: failed to read latest_epoch" << dendl;
+      return r;
+    } else if (epoch <= info.epoch) {
+      r = -EEXIST; // fail with EEXIST if epoch is not newer
+      ldout(cct, 1) << "found existing latest_epoch " << info.epoch
+          << " >= given epoch " << epoch << ", returning r=" << r << dendl;
+      return r;
+    } else {
+      ldout(cct, 20) << "updating latest_epoch from " << info.epoch
+          << " -> " << epoch << " on period=" << id << dendl;
+    }
+
+    r = set_latest_epoch(epoch, exclusive, &objv);
+    if (r == -EEXIST) {
+      continue; // exclusive create raced with another update, retry
+    } else if (r == -ECANCELED) {
+      continue; // write raced with a conflicting version, retry
+    }
+    if (r < 0) {
+      ldout(cct, 0) << "ERROR: failed to write latest_epoch" << dendl;
+      return r;
+    }
+    return 0; // return success
+  }
+
+  return -ECANCELED; // fail after max retries
+}
+
+int RGWPeriod::delete_obj()
+{
+  rgw_pool pool(get_pool(cct));
+
+  // delete the object for each period epoch
+  for (epoch_t e = 1; e <= epoch; e++) {
+    RGWPeriod p{get_id(), e};
+    rgw_raw_obj oid{pool, p.get_period_oid()};
+    int ret = store->delete_system_obj(oid);
+    if (ret < 0) {
+      ldout(cct, 0) << "WARNING: failed to delete period object " << oid
+          << ": " << cpp_strerror(-ret) << dendl;
+    }
+  }
+
+  // delete the .latest_epoch object
+  rgw_raw_obj oid{pool, get_period_oid_prefix() + get_latest_epoch_oid()};
+  int ret = store->delete_system_obj(oid);
+  if (ret < 0) {
+    ldout(cct, 0) << "WARNING: failed to delete period object " << oid
+        << ": " << cpp_strerror(-ret) << dendl;
+  }
+  return ret;
+}
+
+int RGWPeriod::read_info()
+{
+  rgw_pool pool(get_pool(cct));
+
+  bufferlist bl;
+
+  RGWObjectCtx obj_ctx(store);
+  int ret = rgw_get_system_obj(store, obj_ctx, pool, get_period_oid(), bl, NULL, NULL);
+  if (ret < 0) {
+    ldout(cct, 0) << "failed reading obj info from " << pool << ":" << get_period_oid() << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  try {
+    using ceph::decode;
+    auto iter = bl.cbegin();
+    decode(*this, iter);
+  } catch (buffer::error& err) {
+    ldout(cct, 0) << "ERROR: failed to decode obj from " << pool << ":" << get_period_oid() << dendl;
+    return -EIO;
+  }
+
+  return 0;
+}
+
+int RGWPeriod::create(bool exclusive)
+{
+  int ret;
+  
+  /* create unique id */
+  uuid_d new_uuid;
+  char uuid_str[37];
+  new_uuid.generate_random();
+  new_uuid.print(uuid_str);
+  id = uuid_str;
+
+  epoch = FIRST_EPOCH;
+
+  period_map.id = id;
+  
+  ret = store_info(exclusive);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR:  storing info for " << id << ": " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  ret = set_latest_epoch(epoch);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR: setting latest epoch " << id << ": " << cpp_strerror(-ret) << dendl;
+  }
+
+  return ret;
+}
+
+int RGWPeriod::store_info(bool exclusive)
+{
+  rgw_pool pool(get_pool(cct));
+
+  string oid = get_period_oid();
+  bufferlist bl;
+  using ceph::encode;
+  encode(*this, bl);
+
+  return rgw_put_system_obj(store, pool, oid, bl,
+                            exclusive, NULL, real_time(), NULL);
+}
+
+rgw_pool RGWPeriod::get_pool(CephContext *cct)
+{
+  if (cct->_conf->rgw_period_root_pool.empty()) {
+    return rgw_pool(RGW_DEFAULT_PERIOD_ROOT_POOL);
+  }
+  return rgw_pool(cct->_conf->rgw_period_root_pool);
+}
+
+int RGWPeriod::add_zonegroup(const RGWZoneGroup& zonegroup)
+{
+  if (zonegroup.realm_id != realm_id) {
+    return 0;
+  }
+  int ret = period_map.update(zonegroup, cct);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR: updating period map: " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  return store_info(false);
+}
+
+int RGWPeriod::update()
+{
+  ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << get_id() << dendl;
+  list<string> zonegroups;
+  int ret = store->list_zonegroups(zonegroups);
+  if (ret < 0) {
+    ldout(cct, 0) << "ERROR: failed to list zonegroups: " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  // clear zone short ids of removed zones. period_map.update() will add the
+  // remaining zones back
+  period_map.short_zone_ids.clear();
+
+  for (auto& iter : zonegroups) {
+    RGWZoneGroup zg(string(), iter);
+    ret = zg.init(cct, store);
+    if (ret < 0) {
+      ldout(cct, 0) << "WARNING: zg.init() failed: " << cpp_strerror(-ret) << dendl;
+      continue;
+    }
+
+    if (zg.realm_id != realm_id) {
+      ldout(cct, 20) << "skipping zonegroup " << zg.get_name() << " zone realm id " << zg.realm_id << ", not on our realm " << realm_id << dendl;
+      continue;
+    }
+
+    if (zg.master_zone.empty()) {
+      ldout(cct, 0) << "ERROR: zonegroup " << zg.get_name() << " should have a master zone " << dendl;
+      return -EINVAL;
+    }  
+    
+    if (zg.is_master_zonegroup()) {
+      master_zonegroup = zg.get_id();
+      master_zone = zg.master_zone;
+    }
+
+    int ret = period_map.update(zg, cct);
+    if (ret < 0) {
+      return ret;
+    }
+  }
+
+  ret = period_config.read(store, realm_id);
+  if (ret < 0 && ret != -ENOENT) {
+    ldout(cct, 0) << "ERROR: failed to read period config: "
+        << cpp_strerror(ret) << dendl;
+    return ret;
+  }
+  return 0;
+}
+
+int RGWPeriod::reflect()
+{
+  for (auto& iter : period_map.zonegroups) {
+    RGWZoneGroup& zg = iter.second;
+    zg.reinit_instance(cct, store);
+    int r = zg.write(false);
+    if (r < 0) {
+      ldout(cct, 0) << "ERROR: failed to store zonegroup info for zonegroup=" << iter.first << ": " << cpp_strerror(-r) << dendl;
+      return r;
+    }
+    if (zg.is_master_zonegroup()) {
+      // set master as default if no default exists
+      r = zg.set_as_default(true);
+      if (r == 0) {
+        ldout(cct, 1) << "Set the period's master zonegroup " << zg.get_id()
+            << " as the default" << dendl;
+      }
+    }
+  }
+
+  int r = period_config.write(store, realm_id);
+  if (r < 0) {
+    ldout(cct, 0) << "ERROR: failed to store period config: "
+        << cpp_strerror(-r) << dendl;
+    return r;
+  }
+  return 0;
+}
+
+void RGWPeriod::fork()
+{
+  ldout(cct, 20) << __func__ << " realm " << realm_id << " period " << id << dendl;
+  predecessor_uuid = id;
+  id = get_staging_id(realm_id);
+  period_map.reset();
+  realm_epoch++;
+}
+
+static int read_sync_status(RGWRados *store, rgw_meta_sync_status *sync_status)
+{
+  // initialize a sync status manager to read the status
+  RGWMetaSyncStatusManager mgr(store, store->get_async_rados());
+  int r = mgr.init();
+  if (r < 0) {
+    return r;
+  }
+  r = mgr.read_sync_status(sync_status);
+  mgr.stop();
+  return r;
+}
+
+int RGWPeriod::update_sync_status(const RGWPeriod &current_period,
+                                  std::ostream& error_stream,
+                                  bool force_if_stale)
+{
+  rgw_meta_sync_status status;
+  int r = read_sync_status(store, &status);
+  if (r < 0) {
+    ldout(cct, 0) << "period failed to read sync status: "
+        << cpp_strerror(-r) << dendl;
+    return r;
+  }
+
+  std::vector<std::string> 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;
+}
+
+int RGWPeriod::commit(RGWRealm& realm, const RGWPeriod& current_period,
+                      std::ostream& error_stream, bool force_if_stale)
+{
+  ldout(cct, 20) << __func__ << " realm " << realm.get_id() << " period " << current_period.get_id() << dendl;
+  // gateway must be in the master zone to commit
+  if (master_zone != store->get_zone_params().get_id()) {
+    error_stream << "Cannot commit period on zone "
+        << store->get_zone_params().get_id() << ", it must be sent to "
+        "the period's master zone " << master_zone << '.' << std::endl;
+    return -EINVAL;
+  }
+  // period predecessor must match current period
+  if (predecessor_uuid != current_period.get_id()) {
+    error_stream << "Period predecessor " << predecessor_uuid
+        << " does not match current period " << current_period.get_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 (realm_epoch != current_period.get_realm_epoch() + 1) {
+    error_stream << "Period's realm epoch " << realm_epoch
+        << " does not come directly after current realm epoch "
+        << current_period.get_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 (master_zone != current_period.get_master_zone()) {
+    // store the current metadata sync status in the period
+    int r = update_sync_status(current_period, error_stream, force_if_stale);
+    if (r < 0) {
+      ldout(cct, 0) << "failed to update metadata sync status: "
+          << cpp_strerror(-r) << dendl;
+      return r;
+    }
+    // create an object with a new period id
+    r = create(true);
+    if (r < 0) {
+      ldout(cct, 0) << "failed to create new period: " << cpp_strerror(-r) << dendl;
+      return r;
+    }
+    // set as current period
+    r = realm.set_current_period(*this);
+    if (r < 0) {
+      ldout(cct, 0) << "failed to update realm's current period: "
+          << cpp_strerror(-r) << dendl;
+      return r;
+    }
+    ldout(cct, 4) << "Promoted to master zone and committed new period "
+        << id << dendl;
+    realm.notify_new_period(*this);
+    return 0;
+  }
+  // period must be based on current epoch
+  if (epoch != current_period.get_epoch()) {
+    error_stream << "Period epoch " << epoch << " does not match "
+        "predecessor epoch " << current_period.get_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
+  set_id(current_period.get_id());
+  set_epoch(current_period.get_epoch() + 1);
+  set_predecessor(current_period.get_predecessor());
+  realm_epoch = current_period.get_realm_epoch();
+  // write the period to rados
+  int r = store_info(false);
+  if (r < 0) {
+    ldout(cct, 0) << "failed to store period: " << cpp_strerror(-r) << dendl;
+    return r;
+  }
+  // set as latest epoch
+  r = update_latest_epoch(epoch);
+  if (r == -EEXIST) {
+    // already have this epoch (or a more recent one)
+    return 0;
+  }
+  if (r < 0) {
+    ldout(cct, 0) << "failed to set latest epoch: " << cpp_strerror(-r) << dendl;
+    return r;
+  }
+  r = reflect();
+  if (r < 0) {
+    ldout(cct, 0) << "failed to update local objects: " << cpp_strerror(-r) << dendl;
+    return r;
+  }
+  ldout(cct, 4) << "Committed new epoch " << epoch
+      << " for period " << id << dendl;
+  realm.notify_new_period(*this);
+  return 0;
+}
+
+int RGWZoneParams::create_default(bool old_format)
+{
+  name = default_zone_name;
+
+  int r = create();
+  if (r < 0) {
+    return r;
+  }
+
+  if (old_format) {
+    name = id;
+  }
+
+  return r;
+}
+
+
+int get_zones_pool_set(CephContext* cct,
+                       RGWRados* store,
+                       const list<string>& zones,
+                       const string& my_zone_id,
+                       set<rgw_pool>& pool_names)
+{
+  for(auto const& iter : zones) {
+    RGWZoneParams zone(iter);
+    int r = zone.init(cct, store);
+    if (r < 0) {
+      ldout(cct, 0) << "Error: init zone " << iter << ":" << cpp_strerror(-r) << dendl;
+      return r;
+    }
+    if (zone.get_id() != my_zone_id) {
+      pool_names.insert(zone.domain_root);
+      pool_names.insert(zone.metadata_heap);
+      pool_names.insert(zone.control_pool);
+      pool_names.insert(zone.gc_pool);
+      pool_names.insert(zone.log_pool);
+      pool_names.insert(zone.intent_log_pool);
+      pool_names.insert(zone.usage_log_pool);
+      pool_names.insert(zone.user_keys_pool);
+      pool_names.insert(zone.user_email_pool);
+      pool_names.insert(zone.user_swift_pool);
+      pool_names.insert(zone.user_uid_pool);
+      pool_names.insert(zone.otp_pool);
+      pool_names.insert(zone.roles_pool);
+      pool_names.insert(zone.reshard_pool);
+      for(auto& iter : zone.placement_pools) {
+       pool_names.insert(iter.second.index_pool);
+       pool_names.insert(iter.second.data_pool);
+       pool_names.insert(iter.second.data_extra_pool);
+      }
+    }
+  }
+  return 0;
+}
+
+rgw_pool fix_zone_pool_dup(set<rgw_pool> pools,
+                           const string& default_prefix,
+                           const string& default_suffix,
+                           const rgw_pool& suggested_pool)
+{
+  string suggested_name = suggested_pool.to_str();
+
+  string prefix = default_prefix;
+  string suffix = default_suffix;
+
+  if (!suggested_pool.empty()) {
+    prefix = suggested_name.substr(0, suggested_name.find("."));
+    suffix = suggested_name.substr(prefix.length());
+  }
+
+  rgw_pool pool(prefix + suffix);
+  
+  if (pools.find(pool) == pools.end()) {
+    return pool;
+  } else {
+    while(true) {
+      pool =  prefix + "_" + std::to_string(std::rand()) + suffix;
+      if (pools.find(pool) == pools.end()) {
+       return pool;
+      }
+    }
+  }  
+}
+
+int RGWZoneParams::fix_pool_names()
+{
+
+  list<string> zones;
+  int r = store->list_zones(zones);
+  if (r < 0) {
+    ldout(cct, 10) << "WARNING: store->list_zones() returned r=" << r << dendl;
+  }
+
+  set<rgw_pool> pools;
+  r = get_zones_pool_set(cct, store, zones, id, pools);
+  if (r < 0) {
+    ldout(cct, 0) << "Error: get_zones_pool_names" << r << dendl;
+    return r;
+  }
+
+  domain_root = fix_zone_pool_dup(pools, name, ".rgw.meta:root", domain_root);
+  if (!metadata_heap.name.empty()) {
+    metadata_heap = fix_zone_pool_dup(pools, name, ".rgw.meta:heap", metadata_heap);
+  }
+  control_pool = fix_zone_pool_dup(pools, name, ".rgw.control", control_pool);
+  gc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:gc", gc_pool);
+  lc_pool = fix_zone_pool_dup(pools, name ,".rgw.log:lc", lc_pool);
+  log_pool = fix_zone_pool_dup(pools, name, ".rgw.log", log_pool);
+  intent_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:intent", intent_log_pool);
+  usage_log_pool = fix_zone_pool_dup(pools, name, ".rgw.log:usage", usage_log_pool);
+  user_keys_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.keys", user_keys_pool);
+  user_email_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.email", user_email_pool);
+  user_swift_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.swift", user_swift_pool);
+  user_uid_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.uid", user_uid_pool);
+  roles_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:roles", roles_pool);
+  reshard_pool = fix_zone_pool_dup(pools, name, ".rgw.log:reshard", reshard_pool);
+  otp_pool = fix_zone_pool_dup(pools, name, ".rgw.otp", otp_pool);
+
+  for(auto& iter : placement_pools) {
+    iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix,
+                                               iter.second.index_pool);
+    iter.second.data_pool = fix_zone_pool_dup(pools, name, "." + default_storage_pool_suffix,
+                                              iter.second.data_pool);
+    iter.second.data_extra_pool= fix_zone_pool_dup(pools, name, "." + default_storage_extra_pool_suffix,
+                                                   iter.second.data_extra_pool);
+  }
+
+  return 0;
+}
+
+int RGWZoneParams::create(bool exclusive)
+{
+  /* check for old pools config */
+  rgw_raw_obj obj(domain_root, avail_pools);
+  int r = store->raw_obj_stat(obj, NULL, NULL, NULL, NULL, NULL, NULL);
+  if (r < 0) {
+    ldout(store->ctx(), 10) << "couldn't find old data placement pools config, setting up new ones for the zone" << dendl;
+    /* a new system, let's set new placement info */
+    RGWZonePlacementInfo default_placement;
+    default_placement.index_pool = name + "." + default_bucket_index_pool_suffix;
+    default_placement.data_pool =  name + "." + default_storage_pool_suffix;
+    default_placement.data_extra_pool = name + "." + default_storage_extra_pool_suffix;
+    placement_pools["default-placement"] = default_placement;
+  }
+
+  r = fix_pool_names();
+  if (r < 0) {
+    ldout(cct, 0) << "ERROR: fix_pool_names returned r=" << r << dendl;
+    return r;
+  }
+
+  r = RGWSystemMetaObj::create(exclusive);
+  if (r < 0) {
+    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_as_default(true);
+  if (r < 0 && r != -EEXIST) {
+    ldout(cct, 10) << "WARNING: failed to set zone as default, r=" << r << dendl;
+  }
+
+  return 0;
+}
+
+rgw_pool RGWZoneParams::get_pool(CephContext *cct)
+{
+  if (cct->_conf->rgw_zone_root_pool.empty()) {
+    return rgw_pool(RGW_DEFAULT_ZONE_ROOT_POOL);
+  }
+
+  return rgw_pool(cct->_conf->rgw_zone_root_pool);
+}
+
+const string RGWZoneParams::get_default_oid(bool old_format)
+{
+  if (old_format) {
+    return cct->_conf->rgw_default_zone_info_oid;
+  }
+
+  return cct->_conf->rgw_default_zone_info_oid + "." + realm_id;
+}
+
+const string& RGWZoneParams::get_names_oid_prefix()
+{
+  return zone_names_oid_prefix;
+}
+
+const string& RGWZoneParams::get_info_oid_prefix(bool old_format)
+{
+  return zone_info_oid_prefix;
+}
+
+const string& RGWZoneParams::get_predefined_name(CephContext *cct) {
+  return cct->_conf->rgw_zone;
+}
+
+int RGWZoneParams::init(CephContext *cct, RGWRados *store, bool setup_obj, bool old_format)
+{
+  if (name.empty()) {
+    name = cct->_conf->rgw_zone;
+  }
+
+  return RGWSystemMetaObj::init(cct, store, setup_obj, old_format);
+}
+
+int RGWZoneParams::read_default_id(string& default_id, bool old_format)
+{
+  if (realm_id.empty()) {
+    /* try using default realm */
+    RGWRealm realm;
+    int ret = realm.init(cct, store);
+    //no default realm exist
+    if (ret < 0) {
+      return read_id(default_zone_name, default_id);
+    }
+    realm_id = realm.get_id();
+  }
+
+  return RGWSystemMetaObj::read_default_id(default_id, old_format);
+}
+
+
+int RGWZoneParams::set_as_default(bool exclusive)
+{
+  if (realm_id.empty()) {
+    /* try using default realm */
+    RGWRealm realm;
+    int ret = realm.init(cct, store);
+    if (ret < 0) {
+      ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl;
+      return -EINVAL;
+    }
+    realm_id = realm.get_id();
+  }
+
+  return RGWSystemMetaObj::set_as_default(exclusive);
+}
+
+const string& RGWZoneParams::get_compression_type(const string& placement_rule) const
+{
+  static const std::string NONE{"none"};
+  auto p = placement_pools.find(placement_rule);
+  if (p == placement_pools.end()) {
+    return NONE;
+  }
+  const auto& type = p->second.compression_type;
+  return !type.empty() ? type : NONE;
+}
+
+void RGWPeriodMap::encode(bufferlist& bl) const {
+  ENCODE_START(2, 1, bl);
+  encode(id, bl);
+  encode(zonegroups, bl);
+  encode(master_zonegroup, bl);
+  encode(short_zone_ids, bl);
+  ENCODE_FINISH(bl);
+}
+
+void RGWPeriodMap::decode(bufferlist::const_iterator& bl) {
+  DECODE_START(2, bl);
+  decode(id, bl);
+  decode(zonegroups, bl);
+  decode(master_zonegroup, bl);
+  if (struct_v >= 2) {
+    decode(short_zone_ids, bl);
+  }
+  DECODE_FINISH(bl);
+
+  zonegroups_by_api.clear();
+  for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
+       iter != zonegroups.end(); ++iter) {
+    RGWZoneGroup& zonegroup = iter->second;
+    zonegroups_by_api[zonegroup.api_name] = zonegroup;
+    if (zonegroup.is_master_zonegroup()) {
+      master_zonegroup = zonegroup.get_id();
+    }
+  }
+}
+
+// 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;
+  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() <<dendl;
+    return -EINVAL;
+  }
+  map<string, RGWZoneGroup>::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;
+}
+
+int RGWZoneGroupMap::read(CephContext *cct, RGWRados *store)
+{
+
+  RGWPeriod period;
+  int ret = period.init(cct, store);
+  if (ret < 0) {
+    cerr << "failed to read current period info: " << cpp_strerror(ret);
+    return ret;
+  }
+       
+  bucket_quota = period.get_config().bucket_quota;
+  user_quota = period.get_config().user_quota;
+  zonegroups = period.get_map().zonegroups;
+  zonegroups_by_api = period.get_map().zonegroups_by_api;
+  master_zonegroup = period.get_map().master_zonegroup;
+
+  return 0;
+}
+
+void RGWRegionMap::encode(bufferlist& bl) const {
+  ENCODE_START( 3, 1, bl);
+  encode(regions, bl);
+  encode(master_region, bl);
+  encode(bucket_quota, bl);
+  encode(user_quota, bl);
+  ENCODE_FINISH(bl);
+}
+
+void RGWRegionMap::decode(bufferlist::const_iterator& bl) {
+  DECODE_START(3, bl);
+  decode(regions, bl);
+  decode(master_region, bl);
+  if (struct_v >= 2)
+    decode(bucket_quota, bl);
+  if (struct_v >= 3)
+    decode(user_quota, bl);
+  DECODE_FINISH(bl);
+}
+
+void RGWZoneGroupMap::encode(bufferlist& bl) const {
+  ENCODE_START( 3, 1, bl);
+  encode(zonegroups, bl);
+  encode(master_zonegroup, bl);
+  encode(bucket_quota, bl);
+  encode(user_quota, bl);
+  ENCODE_FINISH(bl);
+}
+
+void RGWZoneGroupMap::decode(bufferlist::const_iterator& bl) {
+  DECODE_START(3, bl);
+  decode(zonegroups, bl);
+  decode(master_zonegroup, bl);
+  if (struct_v >= 2)
+    decode(bucket_quota, bl);
+  if (struct_v >= 3)
+    decode(user_quota, bl);
+  DECODE_FINISH(bl);
+
+  zonegroups_by_api.clear();
+  for (map<string, RGWZoneGroup>::iterator iter = zonegroups.begin();
+       iter != zonegroups.end(); ++iter) {
+    RGWZoneGroup& zonegroup = iter->second;
+    zonegroups_by_api[zonegroup.api_name] = zonegroup;
+    if (zonegroup.is_master_zonegroup()) {
+      master_zonegroup = zonegroup.get_name();
+    }
+  }
+}
+
+
diff --git a/src/rgw/rgw_zone.h b/src/rgw/rgw_zone.h
new file mode 100644 (file)
index 0000000..e66d4ab
--- /dev/null
@@ -0,0 +1,941 @@
+#ifndef CEPH_RGW_ZONE_H
+#define CEPH_RGW_ZONE_H
+
+class RGWSystemMetaObj {
+protected:
+  string id;
+  string name;
+
+  CephContext *cct;
+  RGWRados *store;
+
+  int store_name(bool exclusive);
+  int store_info(bool exclusive);
+  int read_info(const string& obj_id, bool old_format = false);
+  int read_id(const string& obj_name, string& obj_id);
+  int read_default(RGWDefaultSystemMetaObjInfo& default_info,
+                  const string& oid);
+  /* read and use default id */
+  int use_default(bool old_format = false);
+
+public:
+  RGWSystemMetaObj() : cct(NULL), store(NULL) {}
+  RGWSystemMetaObj(const string& _name): name(_name), cct(NULL), store(NULL)  {}
+  RGWSystemMetaObj(const string& _id, const string& _name) : id(_id), name(_name), cct(NULL), store(NULL) {}
+  RGWSystemMetaObj(CephContext *_cct, RGWRados *_store): cct(_cct), store(_store){}
+  RGWSystemMetaObj(const string& _name, CephContext *_cct, RGWRados *_store): name(_name), cct(_cct), store(_store){}
+  const string& get_name() const { return name; }
+  const string& get_id() const { return id; }
+
+  void set_name(const string& _name) { name = _name;}
+  void set_id(const string& _id) { id = _id;}
+  void clear_id() { id.clear(); }
+
+  virtual ~RGWSystemMetaObj() {}
+
+  virtual void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(id, bl);
+    encode(name, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  virtual void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+    decode(id, bl);
+    decode(name, bl);
+    DECODE_FINISH(bl);
+  }
+
+  void reinit_instance(CephContext *_cct, RGWRados *_store) {
+    cct = _cct;
+    store = _store;
+  }
+  int init(CephContext *_cct, RGWRados *_store, bool setup_obj = true, bool old_format = false);
+  virtual int read_default_id(string& default_id, bool old_format = false);
+  virtual int set_as_default(bool exclusive = false);
+  int delete_default();
+  virtual int create(bool exclusive = true);
+  int delete_obj(bool old_format = false);
+  int rename(const string& new_name);
+  int update() { return store_info(false);}
+  int update_name() { return store_name(false);}
+  int read();
+  int write(bool exclusive);
+
+  virtual rgw_pool get_pool(CephContext *cct) = 0;
+  virtual const string get_default_oid(bool old_format = false) = 0;
+  virtual const string& get_names_oid_prefix() = 0;
+  virtual const string& get_info_oid_prefix(bool old_format = false) = 0;
+  virtual const string& get_predefined_name(CephContext *cct) = 0;
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWSystemMetaObj)
+
+struct RGWZonePlacementInfo {
+  rgw_pool index_pool;
+  rgw_pool data_pool;
+  rgw_pool data_extra_pool; /* if not set we should use data_pool */
+  RGWBucketIndexType index_type;
+  std::string compression_type;
+
+  RGWZonePlacementInfo() : index_type(RGWBIType_Normal) {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(6, 1, bl);
+    encode(index_pool.to_str(), bl);
+    encode(data_pool.to_str(), bl);
+    encode(data_extra_pool.to_str(), bl);
+    encode((uint32_t)index_type, bl);
+    encode(compression_type, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(6, bl);
+    string index_pool_str;
+    string data_pool_str;
+    decode(index_pool_str, bl);
+    index_pool = rgw_pool(index_pool_str);
+    decode(data_pool_str, bl);
+    data_pool = rgw_pool(data_pool_str);
+    if (struct_v >= 4) {
+      string data_extra_pool_str;
+      decode(data_extra_pool_str, bl);
+      data_extra_pool = rgw_pool(data_extra_pool_str);
+    }
+    if (struct_v >= 5) {
+      uint32_t it;
+      decode(it, bl);
+      index_type = (RGWBucketIndexType)it;
+    }
+    if (struct_v >= 6) {
+      decode(compression_type, bl);
+    }
+    DECODE_FINISH(bl);
+  }
+  const rgw_pool& get_data_extra_pool() const {
+    if (data_extra_pool.empty()) {
+      return data_pool;
+    }
+    return data_extra_pool;
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWZonePlacementInfo)
+
+struct RGWZoneParams : RGWSystemMetaObj {
+  rgw_pool domain_root;
+  rgw_pool metadata_heap;
+  rgw_pool control_pool;
+  rgw_pool gc_pool;
+  rgw_pool lc_pool;
+  rgw_pool log_pool;
+  rgw_pool intent_log_pool;
+  rgw_pool usage_log_pool;
+
+  rgw_pool user_keys_pool;
+  rgw_pool user_email_pool;
+  rgw_pool user_swift_pool;
+  rgw_pool user_uid_pool;
+  rgw_pool roles_pool;
+  rgw_pool reshard_pool;
+  rgw_pool otp_pool;
+
+  RGWAccessKey system_key;
+
+  map<string, RGWZonePlacementInfo> placement_pools;
+
+  string realm_id;
+
+  JSONFormattable tier_config;
+
+  RGWZoneParams() : RGWSystemMetaObj() {}
+  explicit RGWZoneParams(const string& name) : RGWSystemMetaObj(name){}
+  RGWZoneParams(const string& id, const string& name) : RGWSystemMetaObj(id, name) {}
+  RGWZoneParams(const string& id, const string& name, const string& _realm_id)
+    : RGWSystemMetaObj(id, name), realm_id(_realm_id) {}
+
+  rgw_pool get_pool(CephContext *cct) override;
+  const string get_default_oid(bool old_format = false) override;
+  const string& get_names_oid_prefix() override;
+  const string& get_info_oid_prefix(bool old_format = false) override;
+  const string& get_predefined_name(CephContext *cct) override;
+
+  int init(CephContext *_cct, RGWRados *_store, bool setup_obj = true,
+          bool old_format = false);
+  using RGWSystemMetaObj::init;
+  int read_default_id(string& default_id, bool old_format = false) override;
+  int set_as_default(bool exclusive = false) override;
+  int create_default(bool old_format = false);
+  int create(bool exclusive = true) override;
+  int fix_pool_names();
+
+  const string& get_compression_type(const string& placement_rule) const;
+  
+  void encode(bufferlist& bl) const override {
+    ENCODE_START(12, 1, bl);
+    encode(domain_root, bl);
+    encode(control_pool, bl);
+    encode(gc_pool, bl);
+    encode(log_pool, bl);
+    encode(intent_log_pool, bl);
+    encode(usage_log_pool, bl);
+    encode(user_keys_pool, bl);
+    encode(user_email_pool, bl);
+    encode(user_swift_pool, bl);
+    encode(user_uid_pool, bl);
+    RGWSystemMetaObj::encode(bl);
+    encode(system_key, bl);
+    encode(placement_pools, bl);
+    encode(metadata_heap, bl);
+    encode(realm_id, bl);
+    encode(lc_pool, bl);
+    map<string, string, ltstr_nocase> old_tier_config;
+    encode(old_tier_config, bl);
+    encode(roles_pool, bl);
+    encode(reshard_pool, bl);
+    encode(otp_pool, bl);
+    encode(tier_config, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) override {
+    DECODE_START(12, bl);
+    decode(domain_root, bl);
+    decode(control_pool, bl);
+    decode(gc_pool, bl);
+    decode(log_pool, bl);
+    decode(intent_log_pool, bl);
+    decode(usage_log_pool, bl);
+    decode(user_keys_pool, bl);
+    decode(user_email_pool, bl);
+    decode(user_swift_pool, bl);
+    decode(user_uid_pool, bl);
+    if (struct_v >= 6) {
+      RGWSystemMetaObj::decode(bl);
+    } else if (struct_v >= 2) {
+      decode(name, bl);
+      id = name;
+    }
+    if (struct_v >= 3)
+      decode(system_key, bl);
+    if (struct_v >= 4)
+      decode(placement_pools, bl);
+    if (struct_v >= 5)
+      decode(metadata_heap, bl);
+    if (struct_v >= 6) {
+      decode(realm_id, bl);
+    }
+    if (struct_v >= 7) {
+      decode(lc_pool, bl);
+    } else {
+      lc_pool = log_pool.name + ":lc";
+    }
+    map<string, string, ltstr_nocase> old_tier_config;
+    if (struct_v >= 8) {
+      decode(old_tier_config, bl);
+    }
+    if (struct_v >= 9) {
+      decode(roles_pool, bl);
+    } else {
+      roles_pool = name + ".rgw.meta:roles";
+    }
+    if (struct_v >= 10) {
+      decode(reshard_pool, bl);
+    } else {
+      reshard_pool = log_pool.name + ":reshard";
+    }
+    if (struct_v >= 11) {
+      ::decode(otp_pool, bl);
+    } else {
+      otp_pool = name + ".rgw.otp";
+    }
+    if (struct_v >= 12) {
+      ::decode(tier_config, bl);
+    } else {
+      for (auto& kv : old_tier_config) {
+        tier_config.set(kv.first, kv.second);
+      }
+    }
+    DECODE_FINISH(bl);
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+  static void generate_test_instances(list<RGWZoneParams*>& o);
+
+  bool get_placement(const string& placement_id, RGWZonePlacementInfo *placement) const {
+    auto iter = placement_pools.find(placement_id);
+    if (iter == placement_pools.end()) {
+      return false;
+    }
+    *placement = iter->second;
+    return true;
+  }
+
+  /*
+   * return data pool of the head object
+   */
+  bool get_head_data_pool(const string& placement_id, const rgw_obj& obj, rgw_pool *pool) const {
+    const rgw_data_placement_target& explicit_placement = obj.bucket.explicit_placement;
+    if (!explicit_placement.data_pool.empty()) {
+      if (!obj.in_extra_data) {
+        *pool = explicit_placement.data_pool;
+      } else {
+        *pool = explicit_placement.get_data_extra_pool();
+      }
+      return true;
+    }
+    if (placement_id.empty()) {
+      return false;
+    }
+    auto iter = placement_pools.find(placement_id);
+    if (iter == placement_pools.end()) {
+      return false;
+    }
+    if (!obj.in_extra_data) {
+      *pool = iter->second.data_pool;
+    } else {
+      *pool = iter->second.get_data_extra_pool();
+    }
+    return true;
+  }
+};
+WRITE_CLASS_ENCODER(RGWZoneParams)
+
+struct RGWZone {
+  string id;
+  string name;
+  list<string> endpoints;
+  bool log_meta;
+  bool log_data;
+  bool read_only;
+  string tier_type;
+
+  string redirect_zone;
+
+/**
+ * Represents the number of shards for the bucket index object, a value of zero
+ * indicates there is no sharding. By default (no sharding, the name of the object
+ * is '.dir.{marker}', with sharding, the name is '.dir.{marker}.{sharding_id}',
+ * sharding_id is zero-based value. It is not recommended to set a too large value
+ * (e.g. thousand) as it increases the cost for bucket listing.
+ */
+  uint32_t bucket_index_max_shards;
+
+  bool sync_from_all;
+  set<string> sync_from; /* list of zones to sync from */
+
+  RGWZone() : log_meta(false), log_data(false), read_only(false), bucket_index_max_shards(0),
+              sync_from_all(true) {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(7, 1, bl);
+    encode(name, bl);
+    encode(endpoints, bl);
+    encode(log_meta, bl);
+    encode(log_data, bl);
+    encode(bucket_index_max_shards, bl);
+    encode(id, bl);
+    encode(read_only, bl);
+    encode(tier_type, bl);
+    encode(sync_from_all, bl);
+    encode(sync_from, bl);
+    encode(redirect_zone, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(7, bl);
+    decode(name, bl);
+    if (struct_v < 4) {
+      id = name;
+    }
+    decode(endpoints, bl);
+    if (struct_v >= 2) {
+      decode(log_meta, bl);
+      decode(log_data, bl);
+    }
+    if (struct_v >= 3) {
+      decode(bucket_index_max_shards, bl);
+    }
+    if (struct_v >= 4) {
+      decode(id, bl);
+      decode(read_only, bl);
+    }
+    if (struct_v >= 5) {
+      decode(tier_type, bl);
+    }
+    if (struct_v >= 6) {
+      decode(sync_from_all, bl);
+      decode(sync_from, bl);
+    }
+    if (struct_v >= 7) {
+      decode(redirect_zone, bl);
+    }
+    DECODE_FINISH(bl);
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+  static void generate_test_instances(list<RGWZone*>& o);
+
+  bool is_read_only() { return read_only; }
+
+  bool syncs_from(const string& zone_id) const {
+    return (sync_from_all || sync_from.find(zone_id) != sync_from.end());
+  }
+};
+WRITE_CLASS_ENCODER(RGWZone)
+
+struct RGWDefaultZoneGroupInfo {
+  string default_zonegroup;
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(default_zonegroup, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+    decode(default_zonegroup, bl);
+    DECODE_FINISH(bl);
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+  //todo: implement ceph-dencoder
+};
+WRITE_CLASS_ENCODER(RGWDefaultZoneGroupInfo)
+
+struct RGWZoneGroupPlacementTarget {
+  string name;
+  set<string> tags;
+
+  bool user_permitted(list<string>& user_tags) const {
+    if (tags.empty()) {
+      return true;
+    }
+    for (auto& rule : user_tags) {
+      if (tags.find(rule) != tags.end()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(name, bl);
+    encode(tags, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+    decode(name, bl);
+    decode(tags, bl);
+    DECODE_FINISH(bl);
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWZoneGroupPlacementTarget)
+
+
+struct RGWZoneGroup : public RGWSystemMetaObj {
+  string api_name;
+  list<string> endpoints;
+  bool is_master = false;
+
+  string master_zone;
+  map<string, RGWZone> zones;
+
+  map<string, RGWZoneGroupPlacementTarget> placement_targets;
+  string default_placement;
+
+  list<string> hostnames;
+  list<string> hostnames_s3website;
+  // TODO: Maybe convert hostnames to a map<string,list<string>> for
+  // endpoint_type->hostnames
+/*
+20:05 < _robbat21irssi> maybe I do someting like: if (hostname_map.empty()) { populate all map keys from hostnames; };
+20:05 < _robbat21irssi> but that's a later compatability migration planning bit
+20:06 < yehudasa> more like if (!hostnames.empty()) {
+20:06 < yehudasa> for (list<string>::iterator iter = hostnames.begin(); iter != hostnames.end(); ++iter) {
+20:06 < yehudasa> hostname_map["s3"].append(iter->second);
+20:07 < yehudasa> hostname_map["s3website"].append(iter->second);
+20:07 < yehudasa> s/append/push_back/g
+20:08 < _robbat21irssi> inner loop over APIs
+20:08 < yehudasa> yeah, probably
+20:08 < _robbat21irssi> s3, s3website, swift, swith_auth, swift_website
+*/
+  map<string, list<string> > api_hostname_map;
+  map<string, list<string> > api_endpoints_map;
+
+  string realm_id;
+
+  RGWZoneGroup(): is_master(false){}
+  RGWZoneGroup(const std::string &id, const std::string &name):RGWSystemMetaObj(id, name) {}
+  explicit RGWZoneGroup(const std::string &_name):RGWSystemMetaObj(_name) {}
+  RGWZoneGroup(const std::string &_name, bool _is_master, CephContext *cct, RGWRados* store,
+              const string& _realm_id, const list<string>& _endpoints)
+    : RGWSystemMetaObj(_name, cct , store), endpoints(_endpoints), is_master(_is_master),
+      realm_id(_realm_id) {}
+
+  bool is_master_zonegroup() const { return is_master;}
+  void update_master(bool _is_master) {
+    is_master = _is_master;
+    post_process_params();
+  }
+  void post_process_params();
+
+  void encode(bufferlist& bl) const override {
+    ENCODE_START(4, 1, bl);
+    encode(name, bl);
+    encode(api_name, bl);
+    encode(is_master, bl);
+    encode(endpoints, bl);
+    encode(master_zone, bl);
+    encode(zones, bl);
+    encode(placement_targets, bl);
+    encode(default_placement, bl);
+    encode(hostnames, bl);
+    encode(hostnames_s3website, bl);
+    RGWSystemMetaObj::encode(bl);
+    encode(realm_id, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) override {
+    DECODE_START(4, bl);
+    decode(name, bl);
+    decode(api_name, bl);
+    decode(is_master, bl);
+    decode(endpoints, bl);
+    decode(master_zone, bl);
+    decode(zones, bl);
+    decode(placement_targets, bl);
+    decode(default_placement, bl);
+    if (struct_v >= 2) {
+      decode(hostnames, bl);
+    }
+    if (struct_v >= 3) {
+      decode(hostnames_s3website, bl);
+    }
+    if (struct_v >= 4) {
+      RGWSystemMetaObj::decode(bl);
+      decode(realm_id, bl);
+    } else {
+      id = name;
+    }
+    DECODE_FINISH(bl);
+  }
+
+  int read_default_id(string& default_id, bool old_format = false) override;
+  int set_as_default(bool exclusive = false) override;
+  int create_default(bool old_format = false);
+  int equals(const string& other_zonegroup) const;
+  int add_zone(const RGWZoneParams& zone_params, bool *is_master, bool *read_only,
+               const list<string>& endpoints, const string *ptier_type,
+               bool *psync_from_all, list<string>& sync_from, list<string>& sync_from_rm,
+               string *predirect_zone);
+  int remove_zone(const std::string& zone_id);
+  int rename_zone(const RGWZoneParams& zone_params);
+  rgw_pool get_pool(CephContext *cct) override;
+  const string get_default_oid(bool old_region_format = false) override;
+  const string& get_info_oid_prefix(bool old_region_format = false) override;
+  const string& get_names_oid_prefix() override;
+  const string& get_predefined_name(CephContext *cct) override;
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+  static void generate_test_instances(list<RGWZoneGroup*>& o);
+};
+WRITE_CLASS_ENCODER(RGWZoneGroup)
+
+struct RGWPeriodMap
+{
+  string id;
+  map<string, RGWZoneGroup> zonegroups;
+  map<string, RGWZoneGroup> zonegroups_by_api;
+  map<string, uint32_t> short_zone_ids;
+
+  string master_zonegroup;
+
+  void encode(bufferlist& bl) const;
+  void decode(bufferlist::const_iterator& bl);
+
+  int update(const RGWZoneGroup& zonegroup, CephContext *cct);
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+
+  void reset() {
+    zonegroups.clear();
+    zonegroups_by_api.clear();
+    master_zonegroup.clear();
+  }
+
+  uint32_t get_zone_short_id(const string& zone_id) const;
+};
+WRITE_CLASS_ENCODER(RGWPeriodMap)
+
+struct RGWPeriodConfig
+{
+  RGWQuotaInfo bucket_quota;
+  RGWQuotaInfo user_quota;
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(bucket_quota, bl);
+    encode(user_quota, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+    decode(bucket_quota, bl);
+    decode(user_quota, bl);
+    DECODE_FINISH(bl);
+  }
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+
+  // the period config must be stored in a local object outside of the period,
+  // so that it can be used in a default configuration where no realm/period
+  // exists
+  int read(RGWRados *store, const std::string& realm_id);
+  int write(RGWRados *store, const std::string& realm_id);
+
+  static std::string get_oid(const std::string& realm_id);
+  static rgw_pool get_pool(CephContext *cct);
+};
+WRITE_CLASS_ENCODER(RGWPeriodConfig)
+
+/* for backward comaptability */
+struct RGWRegionMap {
+
+  map<string, RGWZoneGroup> regions;
+
+  string master_region;
+
+  RGWQuotaInfo bucket_quota;
+  RGWQuotaInfo user_quota;
+
+  void encode(bufferlist& bl) const;
+  void decode(bufferlist::const_iterator& bl);
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWRegionMap)
+
+struct RGWZoneGroupMap {
+
+  map<string, RGWZoneGroup> zonegroups;
+  map<string, RGWZoneGroup> zonegroups_by_api;
+
+  string master_zonegroup;
+
+  RGWQuotaInfo bucket_quota;
+  RGWQuotaInfo user_quota;
+
+  /* construct the map */
+  int read(CephContext *cct, RGWRados *store);
+
+  void encode(bufferlist& bl) const;
+  void decode(bufferlist::const_iterator& bl);
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWZoneGroupMap)
+
+class RGWRealm;
+
+struct objexp_hint_entry {
+  string tenant;
+  string bucket_name;
+  string bucket_id;
+  rgw_obj_key obj_key;
+  ceph::real_time exp_time;
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(2, 1, bl);
+    encode(bucket_name, bl);
+    encode(bucket_id, bl);
+    encode(obj_key, bl);
+    encode(exp_time, bl);
+    encode(tenant, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    // XXX Do we want DECODE_START_LEGACY_COMPAT_LEN(2, 1, 1, bl); ?
+    DECODE_START(2, bl);
+    decode(bucket_name, bl);
+    decode(bucket_id, bl);
+    decode(obj_key, bl);
+    decode(exp_time, bl);
+    if (struct_v >= 2) {
+      decode(tenant, bl);
+    } else {
+      tenant.clear();
+    }
+    DECODE_FINISH(bl);
+  }
+};
+WRITE_CLASS_ENCODER(objexp_hint_entry)
+
+class RGWPeriod;
+
+class RGWRealm : public RGWSystemMetaObj
+{
+  string current_period;
+  epoch_t epoch{0}; //< realm epoch, incremented for each new period
+
+  int create_control(bool exclusive);
+  int delete_control();
+public:
+  RGWRealm() {}
+  RGWRealm(const string& _id, const string& _name = "") : RGWSystemMetaObj(_id, _name) {}
+  RGWRealm(CephContext *_cct, RGWRados *_store): RGWSystemMetaObj(_cct, _store) {}
+  RGWRealm(const string& _name, CephContext *_cct, RGWRados *_store): RGWSystemMetaObj(_name, _cct, _store){}
+
+  void encode(bufferlist& bl) const override {
+    ENCODE_START(1, 1, bl);
+    RGWSystemMetaObj::encode(bl);
+    encode(current_period, bl);
+    encode(epoch, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) override {
+    DECODE_START(1, bl);
+    RGWSystemMetaObj::decode(bl);
+    decode(current_period, bl);
+    decode(epoch, bl);
+    DECODE_FINISH(bl);
+  }
+
+  int create(bool exclusive = true) override;
+  int delete_obj();
+  rgw_pool get_pool(CephContext *cct) override;
+  const string get_default_oid(bool old_format = false) override;
+  const string& get_names_oid_prefix() override;
+  const string& get_info_oid_prefix(bool old_format = false) override;
+  const string& get_predefined_name(CephContext *cct) override;
+
+  using RGWSystemMetaObj::read_id; // expose as public for radosgw-admin
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+
+  const string& get_current_period() const {
+    return current_period;
+  }
+  int set_current_period(RGWPeriod& period);
+  void clear_current_period_and_epoch() {
+    current_period.clear();
+    epoch = 0;
+  }
+  epoch_t get_epoch() const { return epoch; }
+
+  string get_control_oid();
+  /// send a notify on the realm control object
+  int notify_zone(bufferlist& bl);
+  /// notify the zone of a new period
+  int notify_new_period(const RGWPeriod& period);
+};
+WRITE_CLASS_ENCODER(RGWRealm)
+
+struct RGWPeriodLatestEpochInfo {
+  epoch_t epoch;
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(epoch, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+    decode(epoch, bl);
+    DECODE_FINISH(bl);
+  }
+
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+};
+WRITE_CLASS_ENCODER(RGWPeriodLatestEpochInfo)
+
+class RGWPeriod
+{
+  string id;
+  epoch_t epoch;
+  string predecessor_uuid;
+  std::vector<std::string> sync_status;
+  RGWPeriodMap period_map;
+  RGWPeriodConfig period_config;
+  string master_zonegroup;
+  string master_zone;
+
+  string realm_id;
+  string realm_name;
+  epoch_t realm_epoch{1}; //< realm epoch when period was made current
+
+  CephContext *cct;
+  RGWRados *store;
+
+  int read_info();
+  int read_latest_epoch(RGWPeriodLatestEpochInfo& epoch_info,
+                        RGWObjVersionTracker *objv = nullptr);
+  int use_latest_epoch();
+  int use_current_period();
+
+  const string get_period_oid();
+  const string get_period_oid_prefix();
+
+  // gather the metadata sync status for each shard; only for use on master zone
+  int update_sync_status(const RGWPeriod &current_period,
+                         std::ostream& error_stream, bool force_if_stale);
+
+public:
+  RGWPeriod() : epoch(0), cct(NULL), store(NULL) {}
+
+  RGWPeriod(const string& period_id, epoch_t _epoch = 0)
+    : id(period_id), epoch(_epoch),
+      cct(NULL), store(NULL) {}
+
+  const string& get_id() const { return id; }
+  epoch_t get_epoch() const { return epoch; }
+  epoch_t get_realm_epoch() const { return realm_epoch; }
+  const string& get_predecessor() const { return predecessor_uuid; }
+  const string& get_master_zone() const { return master_zone; }
+  const string& get_master_zonegroup() const { return master_zonegroup; }
+  const string& get_realm() const { return realm_id; }
+  const RGWPeriodMap& get_map() const { return period_map; }
+  RGWPeriodConfig& get_config() { return period_config; }
+  const RGWPeriodConfig& get_config() const { return period_config; }
+  const std::vector<std::string>& get_sync_status() const { return sync_status; }
+  rgw_pool get_pool(CephContext *cct);
+  const string& get_latest_epoch_oid();
+  const string& get_info_oid_prefix();
+
+  void set_user_quota(RGWQuotaInfo& user_quota) {
+    period_config.user_quota = user_quota;
+  }
+
+  void set_bucket_quota(RGWQuotaInfo& bucket_quota) {
+    period_config.bucket_quota = bucket_quota;
+  }
+
+  void set_id(const string& id) {
+    this->id = id;
+    period_map.id = id;
+  }
+  void set_epoch(epoch_t epoch) { this->epoch = epoch; }
+  void set_realm_epoch(epoch_t epoch) { realm_epoch = epoch; }
+
+  void set_predecessor(const string& predecessor)
+  {
+    predecessor_uuid = predecessor;
+  }
+
+  void set_realm_id(const string& _realm_id) {
+    realm_id = _realm_id;
+  }
+
+  int reflect();
+
+  int get_zonegroup(RGWZoneGroup& zonegroup,
+                   const string& zonegroup_id);
+
+  bool is_single_zonegroup() const
+  {
+      return (period_map.zonegroups.size() == 1);
+  }
+
+  /*
+    returns true if there are several zone groups with a least one zone
+   */
+  bool is_multi_zonegroups_with_zones()
+  {
+    int count = 0;
+    for (const auto& zg:  period_map.zonegroups) {
+      if (zg.second.zones.size() > 0) {
+       if (count++ > 0) {
+         return true;
+       }
+      }
+    }
+    return false;
+  }
+
+  int get_latest_epoch(epoch_t& epoch);
+  int set_latest_epoch(epoch_t epoch, bool exclusive = false,
+                       RGWObjVersionTracker *objv = nullptr);
+  // update latest_epoch if the given epoch is higher, else return -EEXIST
+  int update_latest_epoch(epoch_t epoch);
+
+  int init(CephContext *_cct, RGWRados *_store, const string &period_realm_id, const string &period_realm_name = "",
+          bool setup_obj = true);
+  int init(CephContext *_cct, RGWRados *_store, bool setup_obj = true);  
+
+  int create(bool exclusive = true);
+  int delete_obj();
+  int store_info(bool exclusive);
+  int add_zonegroup(const RGWZoneGroup& zonegroup);
+
+  void fork();
+  int update();
+
+  // commit a staging period; only for use on master zone
+  int commit(RGWRealm& realm, const RGWPeriod &current_period,
+             std::ostream& error_stream, bool force_if_stale = false);
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    encode(id, bl);
+    encode(epoch, bl);
+    encode(realm_epoch, bl);
+    encode(predecessor_uuid, bl);
+    encode(sync_status, bl);
+    encode(period_map, bl);
+    encode(master_zone, bl);
+    encode(master_zonegroup, bl);
+    encode(period_config, bl);
+    encode(realm_id, bl);
+    encode(realm_name, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::const_iterator& bl) {
+    DECODE_START(1, bl);
+    decode(id, bl);
+    decode(epoch, bl);
+    decode(realm_epoch, bl);
+    decode(predecessor_uuid, bl);
+    decode(sync_status, bl);
+    decode(period_map, bl);
+    decode(master_zone, bl);
+    decode(master_zonegroup, bl);
+    decode(period_config, bl);
+    decode(realm_id, bl);
+    decode(realm_name, bl);
+    DECODE_FINISH(bl);
+  }
+  void dump(Formatter *f) const;
+  void decode_json(JSONObj *obj);
+
+  static string get_staging_id(const string& realm_id) {
+    return realm_id + ":staging";
+  }
+};
+WRITE_CLASS_ENCODER(RGWPeriod)
+
+#endif
index a53efdda0786fbe4020f3f809af621390d019d6c..15e68cf3613b4fdccb115bc10eb79c06e1c21da6 100644 (file)
@@ -7,10 +7,10 @@
 
 class RGWS_RADOS : public RGWService
 {
+  std::vector<std::string> get_deps();
 public:
   RGWS_RADOS(CephContext *cct) : RGWService(cct, "rados") {}
 
-  std::vector<std::string> deps();
   int create_instance(JSONFormattable& conf, RGWServiceInstanceRef *instance);
 };
 
diff --git a/src/rgw/services/svc_zone.cc b/src/rgw/services/svc_zone.cc
new file mode 100644 (file)
index 0000000..73e099e
--- /dev/null
@@ -0,0 +1,52 @@
+#include "svc_zone.h"
+#include "rgw_zone.h"
+
+RGWZoneParams& RGWSI_Zone::get_zone_params()
+{
+  return *zone_params;
+}
+
+RGWZone& RGWSI_Zone::get_zone()
+{
+  return *zone_public_config;
+}
+
+RGWZoneGroup& RGWSI_Zone::get_zonegroup()
+{
+  return *zonegroup;
+}
+
+int RGWSI_Zone::get_zonegroup(const string& id, RGWZoneGroup& zonegroup)
+{
+  int ret = 0;
+  if (id == get_zonegroup().get_id()) {
+    zonegroup = get_zonegroup();
+  } else if (!current_period->get_id().empty()) {
+    ret = current_period->get_zonegroup(zonegroup, id);
+  }
+  return ret;
+}
+
+RGWRealm& RGWSI_Zone::get_realm()
+{
+  return realm;
+}
+
+bool RGWSI_Zone::zone_is_writeable()
+{
+  return writeable_zone && !get_zone().is_read_only();
+}
+
+uint32_t RGWSI_Zone::get_zone_short_id() const
+{
+  return zone_short_id;
+}
+
+const string& RGWSI_Zone::zone_name()
+{
+  return get_zone_params().get_name();
+}
+const string& RGWSI_Zone::zone_id()
+{
+  return get_zone_params().get_id();
+}
diff --git a/src/rgw/services/svc_zone.h b/src/rgw/services/svc_zone.h
new file mode 100644 (file)
index 0000000..f3c0410
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef CEPH_RGW_SERVICES_ZONE_H
+#define CEPH_RGW_SERVICES_ZONE_H
+
+
+#include "rgw/rgw_service.h"
+
+
+struct RGWZoneGroup;
+struct RGWZone;
+struct RGWZoneParams;
+struct RGWPeriod;
+
+class RGWS_Zone : public RGWService
+{
+public:
+  RGWS_Zone(CephContext *cct) : RGWService(cct, "zone") {}
+
+  int create_instance(JSONFormattable& conf, RGWServiceInstanceRef *instance);
+};
+
+class RGWSI_Zone : public RGWServiceInstance
+{
+  std::unique_ptr<RGWZoneGroup> zonegroup;
+  std::unique_ptr<RGWZone> zone_public_config; /* external zone params, e.g., entrypoints, log flags, etc. */  
+  std::unique_ptr<RGWZoneParams> zone_params; /* internal zone params, e.g., rados pools */
+  std::unique_ptr<RGWPeriod> current_period;
+  uint32_t zone_short_id{0};
+
+  std::vector<std::string> svci_deps = { "sys_obj" };
+  std::vector<std::string> get_deps() {
+    return svci_deps;
+  }
+
+  RGWServiceInstanceRef svc_rados;
+public:
+  RGWSI_Zone(RGWService *svc, CephContext *cct): RGWServiceInstance(svc, cct) {}
+
+  RGWZoneParams& get_zone_params();
+  RGWRealm& get_realm();
+  RGWZoneGroup& get_zonegroup();
+  RGWZone& get_zone();
+
+  const string& zone_name();
+  const string& zone_id();
+  uint32_t get_zone_short_id() const;
+
+  int get_zonegroup(const string& id, RGWZoneGroup& zonegroup);
+
+  bool zone_is_writeable();
+  bool zone_syncs_from(RGWZone& target_zone, RGWZone& source_zone);
+  bool get_redirect_zone_endpoint(string *endpoint);
+};
+
+#endif