set(librgw_common_srcs
services/svc_rados.cc
+ services/svc_zone.cc
rgw_service.cc
rgw_acl.cc
rgw_acl_s3.cc
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 ¤t_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();
#include "rgw_sync_module.h"
#include "rgw_sync_log_trim.h"
+#include "services/svc_zone.h"
+
class RGWWatcher;
class SafeTimer;
class ACLOwner;
struct RGWZoneParams;
class RGWReshard;
class RGWReshardWait;
+struct RGWZone;
+struct RGWPeriod;
/* flags for put_obj_meta() */
#define PUT_OBJ_CREATE 0x01
};
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 ¤t_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 ¤t_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;
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:
quota_handler(NULL),
finisher(NULL),
cr_registry(NULL),
- zone_short_id(0),
rest_master_conn(NULL),
meta_mgr(NULL), data_log(NULL), reshard(NULL) {}
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;
}
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);
const std::string& type() {
return svc_type;
}
- virtual std::vector<std::string> deps() = 0;
virtual int create_instance(JSONFormattable& conf, RGWServiceInstanceRef *instance) = 0;
};
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;
--- /dev/null
+#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 ¤t_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();
+ }
+ }
+}
+
+
--- /dev/null
+#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 ¤t_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 ¤t_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
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);
};
--- /dev/null
+#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();
+}
--- /dev/null
+#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