diff options
author | Yehuda Sadeh <yehuda@redhat.com> | 2018-08-17 03:30:44 +0200 |
---|---|---|
committer | Yehuda Sadeh <yehuda@redhat.com> | 2018-11-08 18:19:29 +0100 |
commit | 7c241f2c1d02c1191cd53022cf41943baae91675 (patch) | |
tree | ecfa245d3d32d696fa984f8b154ec118d21962b1 /src | |
parent | rgw: svc: more zone work, add zone_utils, quota services (diff) | |
download | ceph-7c241f2c1d02c1191cd53022cf41943baae91675.tar.xz ceph-7c241f2c1d02c1191cd53022cf41943baae91675.zip |
rgw: sys_obj service, move zone init to svc_zone
still wip
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/rgw/rgw_period_puller.cc | 2 | ||||
-rw-r--r-- | src/rgw/rgw_rados.cc | 682 | ||||
-rw-r--r-- | src/rgw/rgw_rados.h | 13 | ||||
-rw-r--r-- | src/rgw/rgw_service.cc | 18 | ||||
-rw-r--r-- | src/rgw/rgw_service.h | 10 | ||||
-rw-r--r-- | src/rgw/rgw_zone.cc | 40 | ||||
-rw-r--r-- | src/rgw/rgw_zone.h | 54 | ||||
-rw-r--r-- | src/rgw/services/svc_quota.cc | 2 | ||||
-rw-r--r-- | src/rgw/services/svc_quota.h | 6 | ||||
-rw-r--r-- | src/rgw/services/svc_rados.cc | 7 | ||||
-rw-r--r-- | src/rgw/services/svc_rados.h | 14 | ||||
-rw-r--r-- | src/rgw/services/svc_sys_obj.cc | 316 | ||||
-rw-r--r-- | src/rgw/services/svc_sys_obj.h | 269 | ||||
-rw-r--r-- | src/rgw/services/svc_zone.cc | 710 | ||||
-rw-r--r-- | src/rgw/services/svc_zone.h | 36 |
15 files changed, 1430 insertions, 749 deletions
diff --git a/src/rgw/rgw_period_puller.cc b/src/rgw/rgw_period_puller.cc index 0e3a8f90222..0379739bce1 100644 --- a/src/rgw/rgw_period_puller.cc +++ b/src/rgw/rgw_period_puller.cc @@ -61,7 +61,7 @@ int RGWPeriodPuller::pull(const std::string& period_id, RGWPeriod& period) // try to read the period from rados period.set_id(period_id); period.set_epoch(0); - int r = period.init(store->ctx(), store); + int r = period.init(store->ctx(), store->svc.sysobj.get()); if (r < 0) { if (store->svc.zone->is_meta_master()) { // can't pull if we're the master diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 7f2c4c1d6ce..ced9ebe55e8 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -97,23 +97,7 @@ static string default_bucket_index_pool_suffix = "rgw.buckets.index"; static string default_storage_extra_pool_suffix = "rgw.buckets.non-ec"; static string avail_pools = ".pools.avail"; -static string zone_info_oid_prefix = "zone_info."; -static string zone_names_oid_prefix = "zone_names."; -static string region_info_oid_prefix = "region_info."; -static string zone_group_info_oid_prefix = "zonegroup_info."; -static string realm_names_oid_prefix = "realms_names."; -static string realm_info_oid_prefix = "realms."; -static string default_region_info_oid = "default.region"; -static string default_zone_group_info_oid = "default.zonegroup"; -static string period_info_oid_prefix = "periods."; -static string period_latest_epoch_info_oid = ".latest_epoch"; -static string region_map_oid = "region_map"; -static string zonegroup_map_oid = "zonegroup_map"; static string log_lock_name = "rgw_log_lock"; -static string default_realm_info_oid = "default.realm"; -const string default_zonegroup_name = "default"; -const string default_zone_name = "default"; -static string zonegroup_names_oid_prefix = "zonegroups_names."; static RGWObjCategory main_category = RGW_OBJ_CATEGORY_MAIN; #define RGW_USAGE_OBJ_PREFIX "usage." #define FIRST_EPOCH 1 @@ -831,7 +815,7 @@ public: int notify_all(map<string, RGWRESTConn *>& conn_map, map<int, set<string> >& shards) { rgw_http_param_pair pairs[] = { { "type", "data" }, { "notify", NULL }, - { "source-zone", store->get_zone_params().get_id().c_str() }, + { "source-zone", store->svc.zone->get_zone_params().get_id().c_str() }, { NULL, NULL } }; list<RGWCoroutinesStack *> stacks; @@ -936,7 +920,7 @@ int RGWMetaNotifier::process() ldout(cct, 20) << __func__ << "(): notifying mdlog change, shard_id=" << *iter << dendl; } - notify_mgr.notify_all(store->zone_conn_map, shards); + notify_mgr.notify_all(store->svc.zone->get_zone_conn_map(), shards); return 0; } @@ -974,7 +958,7 @@ int RGWDataNotifier::process() ldout(cct, 20) << __func__ << "(): notifying datalog change, shard_id=" << iter->first << ": " << iter->second << dendl; } - notify_mgr.notify_all(store->zone_data_notify_to_map, shards); + notify_mgr.notify_all(store->svc.zone->get_zone_data_notify_to_map(), shards); return 0; } @@ -1476,7 +1460,7 @@ void RGWIndexCompletionManager::create_completion(const rgw_obj& obj, if (zones_trace) { entry->zones_trace = *zones_trace; } else { - entry->zones_trace.insert(store->get_zone().id); + entry->zones_trace.insert(store->svc.zone->get_zone().id); } *result = entry; @@ -1580,18 +1564,6 @@ void RGWRados::finalize() delete obj_expirer; obj_expirer = NULL; - delete rest_master_conn; - - map<string, RGWRESTConn *>::iterator iter; - for (iter = zone_conn_map.begin(); iter != zone_conn_map.end(); ++iter) { - RGWRESTConn *conn = iter->second; - delete conn; - } - - for (iter = zonegroup_conn_map.begin(); iter != zonegroup_conn_map.end(); ++iter) { - RGWRESTConn *conn = iter->second; - delete conn; - } RGWQuotaHandler::free_handler(quota_handler); if (cr_registry) { cr_registry->put(); @@ -1696,487 +1668,6 @@ int RGWRados::update_service_map(std::map<std::string, std::string>&& status) return 0; } -/** - * Add new connection to connections map - * @param zonegroup_conn_map map which new connection will be added to - * @param zonegroup zonegroup which new connection will connect to - * @param new_connection pointer to new connection instance - */ -static void add_new_connection_to_map(map<string, RGWRESTConn *> &zonegroup_conn_map, - const RGWZoneGroup &zonegroup, RGWRESTConn *new_connection) -{ - // Delete if connection is already exists - map<string, RGWRESTConn *>::iterator iterZoneGroup = zonegroup_conn_map.find(zonegroup.get_id()); - if (iterZoneGroup != zonegroup_conn_map.end()) { - delete iterZoneGroup->second; - } - - // Add new connection to connections map - zonegroup_conn_map[zonegroup.get_id()] = new_connection; -} - -int RGWRados::convert_regionmap() -{ - RGWZoneGroupMap zonegroupmap; - - string pool_name = cct->_conf->rgw_zone_root_pool; - if (pool_name.empty()) { - pool_name = RGW_DEFAULT_ZONE_ROOT_POOL; - } - string oid = region_map_oid; - - rgw_pool pool(pool_name); - bufferlist bl; - RGWObjectCtx obj_ctx(this); - int ret = rgw_get_system_obj(this, obj_ctx, pool, oid, bl, NULL, NULL); - if (ret < 0 && ret != -ENOENT) { - return ret; - } else if (ret == -ENOENT) { - return 0; - } - - try { - auto iter = bl.cbegin(); - decode(zonegroupmap, iter); - } catch (buffer::error& err) { - ldout(cct, 0) << "error decoding regionmap from " << pool << ":" << oid << dendl; - return -EIO; - } - - for (map<string, RGWZoneGroup>::iterator iter = zonegroupmap.zonegroups.begin(); - iter != zonegroupmap.zonegroups.end(); ++iter) { - RGWZoneGroup& zonegroup = iter->second; - ret = zonegroup.init(cct, this, false); - ret = zonegroup.update(); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << "Error could not update zonegroup " << zonegroup.get_name() << ": " << - cpp_strerror(-ret) << dendl; - return ret; - } else if (ret == -ENOENT) { - ret = zonegroup.create(); - if (ret < 0) { - ldout(cct, 0) << "Error could not create " << zonegroup.get_name() << ": " << - cpp_strerror(-ret) << dendl; - return ret; - } - } - } - - current_period.set_user_quota(zonegroupmap.user_quota); - current_period.set_bucket_quota(zonegroupmap.bucket_quota); - - // remove the region_map so we don't try to convert again - rgw_raw_obj obj(pool, oid); - ret = delete_system_obj(obj); - if (ret < 0) { - ldout(cct, 0) << "Error could not remove " << obj - << " after upgrading to zonegroup map: " << cpp_strerror(ret) << dendl; - return ret; - } - - return 0; -} - -/** - * Replace all region configuration with zonegroup for - * backward compatability - * Returns 0 on success, -ERR# on failure. - */ -int RGWRados::replace_region_with_zonegroup() -{ - /* copy default region */ - /* convert default region to default zonegroup */ - string default_oid = cct->_conf->rgw_default_region_info_oid; - if (default_oid.empty()) { - default_oid = default_region_info_oid; - } - - - RGWZoneGroup default_zonegroup; - rgw_pool pool{default_zonegroup.get_pool(cct)}; - string oid = "converted"; - bufferlist bl; - RGWObjectCtx obj_ctx(this); - - int ret = rgw_get_system_obj(this, obj_ctx, pool ,oid, bl, NULL, NULL); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << __func__ << " failed to read converted: ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } else if (ret != -ENOENT) { - ldout(cct, 20) << "System already converted " << dendl; - return 0; - } - - string default_region; - ret = default_zonegroup.init(cct, this, false, true); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed init default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = default_zonegroup.read_default_id(default_region, true); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << __func__ << " failed reading old default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } - - /* convert regions to zonegroups */ - list<string> regions; - ret = list_regions(regions); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << __func__ << " failed to list regions: ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } else if (ret == -ENOENT || regions.empty()) { - RGWZoneParams zoneparams(default_zone_name); - int ret = zoneparams.init(cct, this); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << __func__ << ": error initializing default zone params: " << cpp_strerror(-ret) << dendl; - return ret; - } - /* update master zone */ - RGWZoneGroup default_zg(default_zonegroup_name); - ret = default_zg.init(cct, this); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << __func__ << ": error in initializing default zonegroup: " << cpp_strerror(-ret) << dendl; - return ret; - } - if (ret != -ENOENT && default_zg.master_zone.empty()) { - default_zg.master_zone = zoneparams.get_id(); - return default_zg.update(); - } - return 0; - } - - string master_region, master_zone; - for (list<string>::iterator iter = regions.begin(); iter != regions.end(); ++iter) { - if (*iter != default_zonegroup_name){ - RGWZoneGroup region(*iter); - int ret = region.init(cct, this, true, true); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed init region "<< *iter << ": " << cpp_strerror(-ret) << dendl; - return ret; - } - if (region.is_master_zonegroup()) { - master_region = region.get_id(); - master_zone = region.master_zone; - } - } - } - - /* create realm if there is none. - The realm name will be the region and zone concatenated - realm id will be mds of its name */ - if (realm.get_id().empty() && !master_region.empty() && !master_zone.empty()) { - string new_realm_name = master_region + "." + master_zone; - unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE]; - char md5_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; - MD5 hash; - hash.Update((const unsigned char *)new_realm_name.c_str(), new_realm_name.length()); - hash.Final(md5); - buf_to_hex(md5, CEPH_CRYPTO_MD5_DIGESTSIZE, md5_str); - string new_realm_id(md5_str); - RGWRealm new_realm(new_realm_id,new_realm_name); - ret = new_realm.init(cct, this, false); - if (ret < 0) { - ldout(cct, 0) << __func__ << " Error initing new realm: " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = new_realm.create(); - if (ret < 0 && ret != -EEXIST) { - ldout(cct, 0) << __func__ << " Error creating new realm: " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = new_realm.set_as_default(); - if (ret < 0) { - ldout(cct, 0) << __func__ << " Error setting realm as default: " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = realm.init(cct, this); - if (ret < 0) { - ldout(cct, 0) << __func__ << " Error initing realm: " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = current_period.init(cct, this, realm.get_id(), realm.get_name()); - if (ret < 0) { - ldout(cct, 0) << __func__ << " Error initing current period: " << cpp_strerror(-ret) << dendl; - return ret; - } - } - - list<string>::iterator iter; - /* create zonegroups */ - for (iter = regions.begin(); iter != regions.end(); ++iter) - { - ldout(cct, 0) << __func__ << " Converting " << *iter << dendl; - /* check to see if we don't have already a zonegroup with this name */ - RGWZoneGroup new_zonegroup(*iter); - ret = new_zonegroup.init(cct , this); - if (ret == 0 && new_zonegroup.get_id() != *iter) { - ldout(cct, 0) << __func__ << " zonegroup "<< *iter << " already exists id " << new_zonegroup.get_id () << - " skipping conversion " << dendl; - continue; - } - RGWZoneGroup zonegroup(*iter); - zonegroup.set_id(*iter); - int ret = zonegroup.init(cct, this, true, true); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed init zonegroup: ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } - zonegroup.realm_id = realm.get_id(); - /* fix default region master zone */ - if (*iter == default_zonegroup_name && zonegroup.master_zone.empty()) { - ldout(cct, 0) << __func__ << " Setting default zone as master for default region" << dendl; - zonegroup.master_zone = default_zone_name; - } - ret = zonegroup.update(); - if (ret < 0 && ret != -EEXIST) { - ldout(cct, 0) << __func__ << " failed to update zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } - ret = zonegroup.update_name(); - if (ret < 0 && ret != -EEXIST) { - ldout(cct, 0) << __func__ << " failed to update_name for zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } - if (zonegroup.get_name() == default_region) { - ret = zonegroup.set_as_default(); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed to set_as_default " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } - } - for (map<string, RGWZone>::const_iterator iter = zonegroup.zones.begin(); iter != zonegroup.zones.end(); - ++iter) { - ldout(cct, 0) << __func__ << " Converting zone" << iter->first << dendl; - RGWZoneParams zoneparams(iter->first, iter->first); - zoneparams.set_id(iter->first); - zoneparams.realm_id = realm.get_id(); - ret = zoneparams.init(cct, this); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << __func__ << " failed to init zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl; - return ret; - } else if (ret == -ENOENT) { - ldout(cct, 0) << __func__ << " zone is part of another cluster " << iter->first << " skipping " << dendl; - continue; - } - zonegroup.realm_id = realm.get_id(); - ret = zoneparams.update(); - if (ret < 0 && ret != -EEXIST) { - ldout(cct, 0) << __func__ << " failed to update zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = zoneparams.update_name(); - if (ret < 0 && ret != -EEXIST) { - ldout(cct, 0) << __func__ << " failed to init zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl; - return ret; - } - } - - if (!current_period.get_id().empty()) { - ret = current_period.add_zonegroup(zonegroup); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed to add zonegroup to current_period: " << cpp_strerror(-ret) << dendl; - return ret; - } - } - } - - if (!current_period.get_id().empty()) { - ret = current_period.update(); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed to update new period: " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = current_period.store_info(false); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed to store new period: " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = current_period.reflect(); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed to update local objects: " << cpp_strerror(-ret) << dendl; - return ret; - } - } - - for (auto const& iter : regions) { - RGWZoneGroup zonegroup(iter); - int ret = zonegroup.init(cct, this, true, true); - if (ret < 0) { - ldout(cct, 0) << __func__ << " failed init zonegroup" << iter << ": ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = zonegroup.delete_obj(true); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << __func__ << " failed to delete region " << iter << ": ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } - } - - /* mark as converted */ - ret = rgw_put_system_obj(this, pool, oid, bl, - true, NULL, real_time(), NULL); - if (ret < 0 ) { - ldout(cct, 0) << __func__ << " failed to mark cluster as converted: ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } - - return 0; -} - -int RGWRados::init_zg_from_period(bool *initialized) -{ - *initialized = false; - - if (current_period.get_id().empty()) { - return 0; - } - - int ret = zonegroup.init(cct, this); - ldout(cct, 20) << "period zonegroup init ret " << ret << dendl; - if (ret == -ENOENT) { - return 0; - } - if (ret < 0) { - ldout(cct, 0) << "failed reading zonegroup info: " << cpp_strerror(-ret) << dendl; - return ret; - } - ldout(cct, 20) << "period zonegroup name " << zonegroup.get_name() << dendl; - - map<string, RGWZoneGroup>::const_iterator iter = - current_period.get_map().zonegroups.find(zonegroup.get_id()); - - if (iter != current_period.get_map().zonegroups.end()) { - ldout(cct, 20) << "using current period zonegroup " << zonegroup.get_name() << dendl; - zonegroup = iter->second; - ret = zonegroup.init(cct, this, false); - if (ret < 0) { - ldout(cct, 0) << "failed init zonegroup: " << " " << cpp_strerror(-ret) << dendl; - return ret; - } - ret = zone_params.init(cct, this); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl; - return ret; - } if (ret ==-ENOENT && zonegroup.get_name() == default_zonegroup_name) { - ldout(cct, 10) << " Using default name "<< default_zone_name << dendl; - zone_params.set_name(default_zone_name); - ret = zone_params.init(cct, this); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl; - return ret; - } - } - } - for (iter = current_period.get_map().zonegroups.begin(); - iter != current_period.get_map().zonegroups.end(); ++iter){ - const RGWZoneGroup& zg = iter->second; - // use endpoints from the zonegroup's master zone - auto master = zg.zones.find(zg.master_zone); - if (master == zg.zones.end()) { - // fix missing master zone for a single zone zonegroup - if (zg.master_zone.empty() && zg.zones.size() == 1) { - master = zg.zones.begin(); - ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing master_zone, setting zone " << - master->second.name << " id:" << master->second.id << " as master" << dendl; - if (zonegroup.get_id() == zg.get_id()) { - zonegroup.master_zone = master->second.id; - ret = zonegroup.update(); - if (ret < 0) { - ldout(cct, 0) << "error updating zonegroup : " << cpp_strerror(-ret) << dendl; - return ret; - } - } else { - RGWZoneGroup fixed_zg(zg.get_id(),zg.get_name()); - ret = fixed_zg.init(cct, this); - if (ret < 0) { - ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl; - return ret; - } - fixed_zg.master_zone = master->second.id; - ret = fixed_zg.update(); - if (ret < 0) { - ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl; - return ret; - } - } - } else { - ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing zone for master_zone=" << - zg.master_zone << dendl; - return -EINVAL; - } - } - const auto& endpoints = master->second.endpoints; - add_new_connection_to_map(zonegroup_conn_map, zg, new RGWRESTConn(cct, this, zg.get_id(), endpoints)); - if (!current_period.get_master_zonegroup().empty() && - zg.get_id() == current_period.get_master_zonegroup()) { - rest_master_conn = new RGWRESTConn(cct, this, zg.get_id(), endpoints); - } - } - - *initialized = true; - - return 0; -} - -int RGWRados::init_zg_from_local(bool *creating_defaults) -{ - int ret = zonegroup.init(cct, this); - if ( (ret < 0 && ret != -ENOENT) || (ret == -ENOENT && !cct->_conf->rgw_zonegroup.empty())) { - ldout(cct, 0) << "failed reading zonegroup info: ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } else if (ret == -ENOENT) { - *creating_defaults = true; - ldout(cct, 10) << "Creating default zonegroup " << dendl; - ret = zonegroup.create_default(); - if (ret < 0) { - ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } - ret = zonegroup.init(cct, this); - if (ret < 0) { - ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret) - << dendl; - return ret; - } - } - ldout(cct, 20) << "zonegroup " << zonegroup.get_name() << dendl; - if (zonegroup.is_master_zonegroup()) { - // use endpoints from the zonegroup's master zone - auto master = zonegroup.zones.find(zonegroup.master_zone); - if (master == zonegroup.zones.end()) { - // fix missing master zone for a single zone zonegroup - if (zonegroup.master_zone.empty() && zonegroup.zones.size() == 1) { - master = zonegroup.zones.begin(); - ldout(cct, 0) << "zonegroup " << zonegroup.get_name() << " missing master_zone, setting zone " << - master->second.name << " id:" << master->second.id << " as master" << dendl; - zonegroup.master_zone = master->second.id; - ret = zonegroup.update(); - if (ret < 0) { - ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl; - return ret; - } - } else { - ldout(cct, 0) << "zonegroup " << zonegroup.get_name() << " missing zone for " - "master_zone=" << zonegroup.master_zone << dendl; - return -EINVAL; - } - } - const auto& endpoints = master->second.endpoints; - rest_master_conn = new RGWRESTConn(cct, this, zonegroup.get_id(), endpoints); - } - - return 0; -} - - bool RGWRados::zone_syncs_from(RGWZone& target_zone, RGWZone& source_zone) { return target_zone.syncs_from(source_zone.name) && @@ -2189,99 +1680,12 @@ bool RGWRados::zone_syncs_from(RGWZone& target_zone, RGWZone& source_zone) */ int RGWRados::init_complete() { - int ret = realm.init(cct, this); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << "failed reading realm info: ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } else if (ret != -ENOENT) { - ldout(cct, 20) << "realm " << realm.get_name() << " " << realm.get_id() << dendl; - ret = current_period.init(cct, this, realm.get_id(), realm.get_name()); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << "failed reading current period info: " << " " << cpp_strerror(-ret) << dendl; - return ret; - } - ldout(cct, 20) << "current period " << current_period.get_id() << dendl; - } - - ret = replace_region_with_zonegroup(); - if (ret < 0) { - lderr(cct) << "failed converting region to zonegroup : ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } - - ret = convert_regionmap(); - if (ret < 0) { - lderr(cct) << "failed converting regionmap: " << cpp_strerror(-ret) << dendl; - return ret; - } - - bool zg_initialized = false; - - if (!current_period.get_id().empty()) { - ret = init_zg_from_period(&zg_initialized); - if (ret < 0) { - return ret; - } - } - - bool creating_defaults = false; - bool using_local = (!zg_initialized); - if (using_local) { - ldout(cct, 10) << " cannot find current period zonegroup using local zonegroup" << dendl; - ret = init_zg_from_local(&creating_defaults); - if (ret < 0) { - return ret; - } - // read period_config into current_period - auto& period_config = current_period.get_config(); - ret = period_config.read(this, zonegroup.realm_id); - if (ret < 0 && ret != -ENOENT) { - ldout(cct, 0) << "ERROR: failed to read period config: " - << cpp_strerror(ret) << dendl; - return ret; - } - } - - ldout(cct, 10) << "Cannot find current period zone using local zone" << dendl; - if (creating_defaults && cct->_conf->rgw_zone.empty()) { - ldout(cct, 10) << " Using default name "<< default_zone_name << dendl; - zone_params.set_name(default_zone_name); - } - - ret = zone_params.init(cct, this); - if (ret < 0 && ret != -ENOENT) { - lderr(cct) << "failed reading zone info: ret "<< ret << " " << cpp_strerror(-ret) << dendl; - return ret; - } - map<string, RGWZone>::iterator zone_iter = get_zonegroup().zones.find(zone_params.get_id()); - if (zone_iter == get_zonegroup().zones.end()) { - if (using_local) { - lderr(cct) << "Cannot find zone id=" << zone_params.get_id() << " (name=" << zone_params.get_name() << ")" << dendl; - return -EINVAL; - } - ldout(cct, 1) << "Cannot find zone id=" << zone_params.get_id() << " (name=" << zone_params.get_name() << "), switching to local zonegroup configuration" << dendl; - ret = init_zg_from_local(&creating_defaults); - if (ret < 0) { - return ret; - } - zone_iter = get_zonegroup().zones.find(zone_params.get_id()); - } - if (zone_iter != get_zonegroup().zones.end()) { - zone_public_config = zone_iter->second; - ldout(cct, 20) << "zone " << zone_params.get_name() << dendl; - } else { - lderr(cct) << "Cannot find zone id=" << zone_params.get_id() << " (name=" << zone_params.get_name() << ")" << dendl; - return -EINVAL; - } - - zone_short_id = current_period.get_map().get_zone_short_id(zone_params.get_id()); - if (run_sync_thread) { - ret = sync_modules_manager->create_instance(cct, zone_public_config.tier_type, zone_params.tier_config, &sync_module); + ret = sync_modules_manager->create_instance(cct, svc.zone->get_zone_public_config()->tier_type, svc.zone->get_zone_params()->tier_config, &sync_module); if (ret < 0) { lderr(cct) << "ERROR: failed to init sync module instance, ret=" << ret << dendl; if (ret == -ENOENT) { - lderr(cct) << "ERROR: " << zone_public_config.tier_type + lderr(cct) << "ERROR: " << zone_public_config->tier_type << " sync module does not exist. valid sync modules: " << sync_modules_manager->get_registered_module_names() << dendl; @@ -2290,8 +1694,6 @@ int RGWRados::init_complete() } } - writeable_zone = (zone_public_config.tier_type.empty() || zone_public_config.tier_type == "rgw"); - finisher = new Finisher(cct); finisher->start(); @@ -2544,6 +1946,12 @@ int RGWRados::initialize() return ret; } + JSONFormattable sysobj_svc_conf; + ret = svc_registry->get_instance("sys_obj", quota_svc_conf, &svc.sysobj); + if (ret < 0) { + return ret; + } + host_id = svc.zone_utils->gen_host_id(); ret = init_rados(); @@ -2591,72 +1999,6 @@ int RGWRados::list_raw_prefixed_objs(const rgw_pool& pool, const string& prefix, return 0; } -int RGWRados::list_regions(list<string>& regions) -{ - RGWZoneGroup zonegroup; - - return list_raw_prefixed_objs(zonegroup.get_pool(cct), region_info_oid_prefix, regions); -} - -int RGWRados::list_zonegroups(list<string>& zonegroups) -{ - RGWZoneGroup zonegroup; - - return list_raw_prefixed_objs(zonegroup.get_pool(cct), zonegroup_names_oid_prefix, zonegroups); -} - -int RGWRados::list_zones(list<string>& zones) -{ - RGWZoneParams zoneparams; - - return list_raw_prefixed_objs(zoneparams.get_pool(cct), zone_names_oid_prefix, zones); -} - -int RGWRados::list_realms(list<string>& realms) -{ - RGWRealm realm(cct, this); - return list_raw_prefixed_objs(realm.get_pool(cct), realm_names_oid_prefix, realms); -} - -int RGWRados::list_periods(list<string>& periods) -{ - RGWPeriod period; - list<string> raw_periods; - int ret = list_raw_prefixed_objs(period.get_pool(cct), period.get_info_oid_prefix(), raw_periods); - if (ret < 0) { - return ret; - } - for (const auto& oid : raw_periods) { - size_t pos = oid.find("."); - if (pos != std::string::npos) { - periods.push_back(oid.substr(0, pos)); - } else { - periods.push_back(oid); - } - } - periods.sort(); // unique() only detects duplicates if they're adjacent - periods.unique(); - return 0; -} - - -int RGWRados::list_periods(const string& current_period, list<string>& periods) -{ - int ret = 0; - string period_id = current_period; - while(!period_id.empty()) { - RGWPeriod period(period_id); - ret = period.init(cct, this); - if (ret < 0) { - return ret; - } - periods.push_back(period.get_id()); - period_id = period.get_predecessor(); - } - - return ret; -} - /** * Open the pool used as root for this gateway * Returns: 0 on success, -ERR# otherwise. diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 04f68dca959..c0429ddc329 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -49,6 +49,7 @@ class RGWReshardWait; class RGWSI_Zone; class RGWSI_ZoneUtils; class RGWSI_Quota; +class RGWSI_SysObj; /* flags for put_obj_meta() */ #define PUT_OBJ_CREATE 0x01 @@ -1352,6 +1353,7 @@ public: std::shared_ptr<RGWSI_Zone> zone; std::shared_ptr<RGWSI_ZoneUtils> zone_utils; std::shared_ptr<RGWSI_Quota> quota; + std::shared_ptr<RGWSI_SysObj> sysobj; } svc; /** @@ -1411,13 +1413,6 @@ public: string list_raw_objs_get_cursor(RGWListRawObjsCtx& ctx); int list_raw_prefixed_objs(const rgw_pool& pool, const string& prefix, list<string>& result); - int list_zonegroups(list<string>& zonegroups); - int list_regions(list<string>& regions); - int list_zones(list<string>& zones); - int list_realms(list<string>& realms); - int list_periods(list<string>& periods); - int list_periods(const string& current_period, list<string>& periods); - void tick(); CephContext *ctx() { return cct; } /** do all necessary setup of the storage device */ @@ -1432,11 +1427,7 @@ public: } /** Initialize the RADOS instance and prepare to do other ops */ virtual int init_rados(); - int init_zg_from_period(bool *initialized); - int init_zg_from_local(bool *creating_defaults); int init_complete(); - int replace_region_with_zonegroup(); - int convert_regionmap(); int initialize(); void finalize(); diff --git a/src/rgw/rgw_service.cc b/src/rgw/rgw_service.cc index d59361b251e..6b37c68e899 100644 --- a/src/rgw/rgw_service.cc +++ b/src/rgw/rgw_service.cc @@ -1,12 +1,17 @@ #include "rgw_service.h" #include "services/svc_rados.h" +#include "services/svc_zone.h" +#include "services/svc_zone_utils.h" +#include "services/svc_quota.h" +#include "services/svc_sys_obj.h" #define dout_subsys ceph_subsys_rgw RGWServiceInstance::~RGWServiceInstance() { if (svc) { + shutdown(); svc->svc_registry->remove_instance(this); } } @@ -14,6 +19,10 @@ RGWServiceInstance::~RGWServiceInstance() void RGWServiceRegistry::register_all(CephContext *cct) { services["rados"] = make_shared<RGWS_RADOS>(cct); + services["zone"] = make_shared<RGWS_Zone>(cct); + services["zone_utils"] = make_shared<RGWS_ZoneUtils>(cct); + services["quota"] = make_shared<RGWS_Quota>(cct); + services["sys_obj"] = make_shared<RGWS_SysObj>(cct); } bool RGWServiceRegistry::find(const string& name, RGWServiceRef *svc) @@ -76,8 +85,9 @@ int RGWServiceRegistry::get_instance(RGWServiceRef& svc, dep_refs[dep_id] = dep_ref; } - r = instance_ref->init(conf, dep_refs); + r = instance_ref->load(conf, dep_refs); if (r < 0) { + ldout(cct, 0) << "ERROR: service instance load return error: service=" << svc->type() << " r=" << r << dendl; return r; } @@ -89,6 +99,12 @@ int RGWServiceRegistry::get_instance(RGWServiceRef& svc, *ref = iinfo.ref; + r = instance_ref->init(); + if (r < 0) { + ldout(cct, 0) << "ERROR: service instance init return error: service=" << svc->type() << " r=" << r << dendl; + return r; + } + return 0; } diff --git a/src/rgw/rgw_service.h b/src/rgw/rgw_service.h index 1681e923a86..da8bce523cf 100644 --- a/src/rgw/rgw_service.h +++ b/src/rgw/rgw_service.h @@ -58,12 +58,20 @@ protected: virtual std::map<std::string, dependency> get_deps() { return std::map<std::string, dependency>(); } - virtual int init(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) = 0; + virtual int load(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) = 0; + virtual int init() { + return 0; + } + virtual void shutdown() {} public: RGWServiceInstance(RGWService *svc, CephContext *_cct) : cct(_cct) {} virtual ~RGWServiceInstance(); + CephContext *ctx() { + return cct; + } + string get_title() { return svc->type() + ":" + svc_instance; } diff --git a/src/rgw/rgw_zone.cc b/src/rgw/rgw_zone.cc index ce2e9563163..54a90689207 100644 --- a/src/rgw/rgw_zone.cc +++ b/src/rgw/rgw_zone.cc @@ -1,5 +1,7 @@ #include "rgw_zone.h" +#include "services/svc_sys_obj.h" + void RGWDefaultZoneGroupInfo::dump(Formatter *f) const { encode_json("default_zonegroup", default_zonegroup, f); } @@ -35,7 +37,7 @@ int RGWZoneGroup::create_default(bool old_format) RGWZoneParams zone_params(default_zone_name); - int r = zone_params.init(cct, store, false); + int r = zone_params.init(cct, zone_svc, false); if (r < 0) { ldout(cct, 0) << "create_default: error initializing zone params: " << cpp_strerror(-r) << dendl; return r; @@ -48,7 +50,7 @@ int RGWZoneGroup::create_default(bool old_format) } 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); + r = zone_params.init(cct, zone_svc); if (r < 0) { ldout(cct, 0) << "create_default: error in init existing zone params: " << cpp_strerror(-r) << dendl; return r; @@ -71,7 +73,7 @@ int RGWZoneGroup::create_default(bool old_format) if (r == -EEXIST) { ldout(cct, 10) << "create_default() returned -EEXIST, we raced with another zonegroup creation" << dendl; id.clear(); - r = init(cct, store); + r = init(cct, zone_svc); if (r < 0) { return r; } @@ -172,11 +174,14 @@ int RGWZoneGroup::add_zone(const RGWZoneParams& zone_params, bool *is_master, bo } if (ptier_type) { zone.tier_type = *ptier_type; +#warning FIXME +#if 0 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; +#endif return -ENOENT; } } @@ -227,7 +232,7 @@ void RGWZoneGroup::post_process_params() zone.log_data = log_data; RGWZoneParams zone_params(zone.id, zone.name); - int ret = zone_params.init(cct, store); + int ret = zone_params.init(cct, zone_svc); if (ret < 0) { ldout(cct, 0) << "WARNING: could not read zone params for zone id=" << zone.id << " name=" << zone.name << dendl; continue; @@ -270,7 +275,7 @@ 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); + int ret = realm.init(cct, zone_svc); // no default realm exist if (ret < 0) { return read_id(default_zonegroup_name, default_id); @@ -286,7 +291,7 @@ int RGWZoneGroup::set_as_default(bool exclusive) if (realm_id.empty()) { /* try using default realm */ RGWRealm realm; - int ret = realm.init(cct, store); + int ret = realm.init(cct, zone_svc); if (ret < 0) { ldout(cct, 10) << "could not read realm id: " << cpp_strerror(-ret) << dendl; return -EINVAL; @@ -297,10 +302,10 @@ int RGWZoneGroup::set_as_default(bool exclusive) return RGWSystemMetaObj::set_as_default(exclusive); } -int RGWSystemMetaObj::init(CephContext *_cct, RGWRados *_store, bool setup_obj, bool old_format) +int RGWSystemMetaObj::init(CephContext *_cct, RGWSI_Zone *_zone_svc, bool setup_obj, bool old_format) { cct = _cct; - store = _store; + zone_svc = _zone_svc; if (!setup_obj) return 0; @@ -338,7 +343,8 @@ int RGWSystemMetaObj::read_default(RGWDefaultSystemMetaObjInfo& default_info, co using ceph::decode; auto pool = get_pool(cct); bufferlist bl; - RGWObjectCtx obj_ctx(store); + RGWSysObjectCtx obj_ctx = sysobj_svc->get_obj_ctx(); + int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); if (ret < 0) return ret; @@ -402,7 +408,8 @@ int RGWSystemMetaObj::read_id(const string& obj_name, string& object_id) string oid = get_names_oid_prefix() + obj_name; - RGWObjectCtx obj_ctx(store); + RGWSysObjectCtx obj_ctx = sysobj_svc->get_obj_ctx(); + int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); if (ret < 0) { return ret; @@ -522,7 +529,8 @@ int RGWSystemMetaObj::read_info(const string& obj_id, bool old_format) string oid = get_info_oid_prefix(old_format) + obj_id; - RGWObjectCtx obj_ctx(store); + RGWSysObjectCtx obj_ctx = sysobj_svc->get_obj_ctx(); + 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; @@ -803,7 +811,8 @@ rgw_pool RGWPeriodConfig::get_pool(CephContext *cct) int RGWPeriodConfig::read(RGWRados *store, const std::string& realm_id) { - RGWObjectCtx obj_ctx(store); + RGWSysObjectCtx obj_ctx = sysobj_svc->get_obj_ctx(); + const auto& pool = get_pool(store->ctx()); const auto& oid = get_oid(realm_id); bufferlist bl; @@ -954,7 +963,8 @@ int RGWPeriod::read_latest_epoch(RGWPeriodLatestEpochInfo& info, rgw_pool pool(get_pool(cct)); bufferlist bl; - RGWObjectCtx obj_ctx(store); + RGWSysObjectCtx obj_ctx = sysobj_svc->get_obj_ctx(); + 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; @@ -1093,7 +1103,9 @@ int RGWPeriod::read_info() bufferlist bl; - RGWObjectCtx obj_ctx(store); + RGWSysObjectCtx obj_ctx = sysobj_svc->get_obj_ctx(); + + 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; diff --git a/src/rgw/rgw_zone.h b/src/rgw/rgw_zone.h index 94708fb7264..48ada717e4c 100644 --- a/src/rgw/rgw_zone.h +++ b/src/rgw/rgw_zone.h @@ -41,13 +41,15 @@ struct RGWDefaultSystemMetaObjInfo { }; WRITE_CLASS_ENCODER(RGWDefaultSystemMetaObjInfo) +class RGWSI_SysObj; + class RGWSystemMetaObj { protected: string id; string name; - CephContext *cct; - RGWRados *store; + CephContext *cct{nullptr}; + RGWSI_SysObj *sysobj_svc{nullptr}; int store_name(bool exclusive); int store_info(bool exclusive); @@ -59,11 +61,12 @@ protected: 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){} + RGWSystemMetaObj() {} + RGWSystemMetaObj(const string& _name): name(_name) {} + RGWSystemMetaObj(const string& _id, const string& _name) : id(_id), name(_name) {} + RGWSystemMetaObj(CephContext *_cct, RGWSI_SysObj *_sysobj_svc): cct(_cct), sysobj_svc(_sysobj_svc){} + RGWSystemMetaObj(const string& _name, CephContext *_cct, RGWSI_SysObj *_sysobj_svc): name(_name), cct(_cct), sysobj_svc(_sysobj_svc){} + const string& get_name() const { return name; } const string& get_id() const { return id; } @@ -87,11 +90,11 @@ public: DECODE_FINISH(bl); } - void reinit_instance(CephContext *_cct, RGWRados *_store) { + void reinit_instance(CephContext *_cct, RGWSI_SysObj *_sysobj_svc) { cct = _cct; - store = _store; + sysobj_svc = _sysobj_svc; } - int init(CephContext *_cct, RGWRados *_store, bool setup_obj = true, bool old_format = false); + int init(CephContext *_cct, RGWSI_SysObj *_sysobj_svc, 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(); @@ -205,7 +208,7 @@ struct RGWZoneParams : RGWSystemMetaObj { 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, + int init(CephContext *_cct, RGWSI_SysObj *_sysobj_svc, bool setup_obj = true, bool old_format = false); using RGWSystemMetaObj::init; int read_default_id(string& default_id, bool old_format = false) override; @@ -520,9 +523,9 @@ struct RGWZoneGroup : public RGWSystemMetaObj { 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, + RGWZoneGroup(const std::string &_name, bool _is_master, CephContext *cct, RGWSI_SysObj* sysobj_svc, const string& _realm_id, const list<string>& _endpoints) - : RGWSystemMetaObj(_name, cct , store), endpoints(_endpoints), is_master(_is_master), + : RGWSystemMetaObj(_name, cct , sysobj_svc), endpoints(_endpoints), is_master(_is_master), realm_id(_realm_id) {} bool is_master_zonegroup() const { return is_master;} @@ -648,8 +651,8 @@ struct RGWPeriodConfig // 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); + int read(RGWSI_SysObj *sysobj_svc, const std::string& realm_id); + int write(RGWSI_SysObj *sysobj_svc, const std::string& realm_id); static std::string get_oid(const std::string& realm_id); static rgw_pool get_pool(CephContext *cct); @@ -685,7 +688,7 @@ struct RGWZoneGroupMap { RGWQuotaInfo user_quota; /* construct the map */ - int read(CephContext *cct, RGWRados *store); + int read(CephContext *cct, RGWSI_SysObj *sysobj_svc); void encode(bufferlist& bl) const; void decode(bufferlist::const_iterator& bl); @@ -708,8 +711,8 @@ class RGWRealm : public RGWSystemMetaObj 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){} + RGWRealm(CephContext *_cct, RGWSI_SysObj *_sysobj_svc): RGWSystemMetaObj(_cct, _sysobj_svc) {} + RGWRealm(const string& _name, CephContext *_cct, RGWSI_SysObj *_sysobj_svc): RGWSystemMetaObj(_name, _cct, _sysobj_svc){} void encode(bufferlist& bl) const override { ENCODE_START(1, 1, bl); @@ -781,7 +784,7 @@ WRITE_CLASS_ENCODER(RGWPeriodLatestEpochInfo) class RGWPeriod { string id; - epoch_t epoch; + epoch_t epoch{0}; string predecessor_uuid; std::vector<std::string> sync_status; RGWPeriodMap period_map; @@ -793,8 +796,8 @@ class RGWPeriod string realm_name; epoch_t realm_epoch{1}; //< realm epoch when period was made current - CephContext *cct; - RGWRados *store; + CephContext *cct{nullptr}; + RGWSI_SysObj *sysobj_svc{nullptr}; int read_info(); int read_latest_epoch(RGWPeriodLatestEpochInfo& epoch_info, @@ -810,11 +813,10 @@ class RGWPeriod std::ostream& error_stream, bool force_if_stale); public: - RGWPeriod() : epoch(0), cct(NULL), store(NULL) {} + RGWPeriod() {} RGWPeriod(const string& period_id, epoch_t _epoch = 0) - : id(period_id), epoch(_epoch), - cct(NULL), store(NULL) {} + : id(period_id), epoch(_epoch) {} const string& get_id() const { return id; } epoch_t get_epoch() const { return epoch; } @@ -887,9 +889,9 @@ public: // 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 = "", + int init(CephContext *_cct, RGWSI_SysObj *_sysobj_svc, 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 init(CephContext *_cct, RGWSI_SysObj *_sysobj_svc, bool setup_obj = true); int create(bool exclusive = true); int delete_obj(); diff --git a/src/rgw/services/svc_quota.cc b/src/rgw/services/svc_quota.cc index 8fda921c7a7..267c265babf 100644 --- a/src/rgw/services/svc_quota.cc +++ b/src/rgw/services/svc_quota.cc @@ -18,7 +18,7 @@ std::map<string, RGWServiceInstance::dependency> RGWSI_Quota::get_deps() return deps; } -int RGWSI_Quota::init(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) +int RGWSI_Quota::load(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) { zone_svc = static_pointer_cast<RGWSI_Zone>(dep_refs["zone_dep"]); assert(zone_svc); diff --git a/src/rgw/services/svc_quota.h b/src/rgw/services/svc_quota.h index 425fc37f18d..a1e56d2c7a7 100644 --- a/src/rgw/services/svc_quota.h +++ b/src/rgw/services/svc_quota.h @@ -12,15 +12,15 @@ class RGWS_Quota : public RGWService public: RGWS_Quota(CephContext *cct) : RGWService(cct, "quota") {} - int create_instance(const std::string& conf, RGWServiceInstanceRef *instance); + int create_instance(const std::string& conf, RGWServiceInstanceRef *instance) override; }; class RGWSI_Quota : public RGWServiceInstance { std::shared_ptr<RGWSI_Zone> zone_svc; - std::map<std::string, RGWServiceInstance::dependency> get_deps(); - int init(const std::string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs); + std::map<std::string, RGWServiceInstance::dependency> get_deps() override; + int load(const std::string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) override; public: RGWSI_Quota(RGWService *svc, CephContext *cct): RGWServiceInstance(svc, cct) {} diff --git a/src/rgw/services/svc_rados.cc b/src/rgw/services/svc_rados.cc index 4c587a985e8..b0b4d02da8c 100644 --- a/src/rgw/services/svc_rados.cc +++ b/src/rgw/services/svc_rados.cc @@ -47,7 +47,7 @@ static int init_ioctx(CephContext *cct, librados::Rados *rados, const rgw_pool& return 0; } -int RGWSI_RADOS::init(const string& conf, map<string, RGWServiceInstanceRef>& deps) +int RGWSI_RADOS::load(const string& conf, map<string, RGWServiceInstanceRef>& deps) { auto handles = std::vector<librados::Rados>{static_cast<size_t>(cct->_conf->rgw_num_rados_handles)}; @@ -131,3 +131,8 @@ int RGWSI_RADOS::Obj::aio_operate(librados::AioCompletion *c, librados::ObjectWr { return ref.ioctx.aio_operate(ref.oid, c, op); } + +uint64_t RGWSI_RADOS::Obj::get_last_version() +{ + return ref.ioctx.get_last_version(); +} diff --git a/src/rgw/services/svc_rados.h b/src/rgw/services/svc_rados.h index 32585357814..a49f78beb66 100644 --- a/src/rgw/services/svc_rados.h +++ b/src/rgw/services/svc_rados.h @@ -12,7 +12,7 @@ class RGWS_RADOS : public RGWService public: RGWS_RADOS(CephContext *cct) : RGWService(cct, "rados") {} - int create_instance(const string& conf, RGWServiceInstanceRef *instance); + int create_instance(const string& conf, RGWServiceInstanceRef *instance) override; }; struct rgw_rados_ref { @@ -29,7 +29,8 @@ class RGWSI_RADOS : public RGWServiceInstance RWLock handle_lock; std::map<pthread_t, int> rados_map; - int init(const string& conf, std::map<std::string, RGWServiceInstanceRef>& deps); + int load(const string& conf, std::map<std::string, RGWServiceInstanceRef>& deps) override; + librados::Rados* get_rados_handle(); int open_pool_ctx(const rgw_pool& pool, librados::IoCtx& io_ctx); public: @@ -41,7 +42,7 @@ public: class Obj { friend class RGWSI_RADOS; - RGWSI_RADOS *rados_svc; + RGWSI_RADOS *rados_svc{nullptr}; rgw_rados_ref ref; void init(const rgw_raw_obj& obj); @@ -51,17 +52,20 @@ public: } public: + Obj() {} Obj(const Obj& o) : rados_svc(o.rados_svc), ref(o.ref) {} - Obj(const Obj&& o) : rados_svc(o.rados_svc), - ref(std::move(o.ref)) {} + Obj(Obj&& o) : rados_svc(o.rados_svc), + ref(std::move(o.ref)) {} int open(); int operate(librados::ObjectWriteOperation *op); int operate(librados::ObjectReadOperation *op, bufferlist *pbl); int aio_operate(librados::AioCompletion *c, librados::ObjectWriteOperation *op); + + uint64_t get_last_version(); }; Obj obj(const rgw_raw_obj& o) { diff --git a/src/rgw/services/svc_sys_obj.cc b/src/rgw/services/svc_sys_obj.cc new file mode 100644 index 00000000000..e0bd5856719 --- /dev/null +++ b/src/rgw/services/svc_sys_obj.cc @@ -0,0 +1,316 @@ +#include "svc_sys_obj.h" +#include "svc_rados.h" + +int RGWS_SysObj::create_instance(const string& conf, RGWServiceInstanceRef *instance) +{ + instance->reset(new RGWSI_SysObj(this, cct)); + return 0; +} + +std::map<string, RGWServiceInstance::dependency> RGWSI_SysObj::get_deps() +{ + RGWServiceInstance::dependency dep1 = { .name = "rados", + .conf = "{}" }; + RGWServiceInstance::dependency dep2 = { .name = "zone", + .conf = "{}" }; + map<string, RGWServiceInstance::dependency> deps; + deps["rados_dep"] = dep1 + deps["zone_dep"] = dep2 + return deps; +} + +int RGWSI_SysObj::load(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) +{ + rados_svc = static_pointer_cast<RGWSI_RADOS>(dep_refs["rados_dep"]); + assert(rados_svc); + + zone_svc = static_pointer_cast<RGWSI_Zone>(dep_refs["zone_dep"]); + assert(zone_svc); + + return 0; +} + +int RGWSI_SysObj::get_rados_obj(RGWSI_Zone *zone_svc, + rgw_raw_obj& obj, + RGWSI_Rados::Obj *pobj) +{ + zone_svc->canonicalize_raw_obj(&obj); + + *pobj = rados_svc->obj(obj); + int r = pobj->open(); + if (r < 0) { + return r; + } + + return 0; +} + +int RGWSI_SysObj::get_system_obj_state_impl(RGWSysObjectCtx *rctx, rgw_raw_obj& obj, RGWSysObjState **state, RGWObjVersionTracker *objv_tracker) +{ + if (obj.empty()) { + return -EINVAL; + } + + RGWSysObjState *s = rctx->get_state(obj); + ldout(cct, 20) << "get_system_obj_state: rctx=" << (void *)rctx << " obj=" << obj << " state=" << (void *)s << " s->prefetch_data=" << s->prefetch_data << dendl; + *state = s; + if (s->has_attrs) { + return 0; + } + + s->obj = obj; + + int r = raw_stat(obj, &s->size, &s->mtime, &s->epoch, &s->attrset, (s->prefetch_data ? &s->data : NULL), objv_tracker); + if (r == -ENOENT) { + s->exists = false; + s->has_attrs = true; + s->mtime = real_time(); + return 0; + } + if (r < 0) + return r; + + s->exists = true; + s->has_attrs = true; + s->obj_tag = s->attrset[RGW_ATTR_ID_TAG]; + + if (s->obj_tag.length()) + ldout(cct, 20) << "get_system_obj_state: setting s->obj_tag to " + << s->obj_tag.c_str() << dendl; + else + ldout(cct, 20) << "get_system_obj_state: s->obj_tag was set empty" << dendl; + + return 0; +} + +int RGWSI_SysObj::get_system_obj_state(RGWSysObjectCtx *rctx, rgw_raw_obj& obj, RGWSysObjState **state, RGWObjVersionTracker *objv_tracker) +{ + int ret; + + do { + ret = get_system_obj_state_impl(rctx, obj, state, objv_tracker); + } while (ret == -EAGAIN); + + return ret; +} + +int RGWSI_SysObj::raw_stat(rgw_raw_obj& obj, uint64_t *psize, real_time *pmtime, uint64_t *epoch, + map<string, bufferlist> *attrs, bufferlist *first_chunk, + RGWObjVersionTracker *objv_tracker) +{ + RGWSI_Rados::Obj rados_obj; + int r = get_rados_obj(obj, &rados_obj); + if (r < 0) { + return r; + } + + map<string, bufferlist> unfiltered_attrset; + uint64_t size = 0; + struct timespec mtime_ts; + + librados::ObjectReadOperation op; + if (objv_tracker) { + objv_tracker->prepare_op_for_read(&op); + } + if (attrs) { + op.getxattrs(&unfiltered_attrset, NULL); + } + if (psize || pmtime) { + op.stat2(&size, &mtime_ts, NULL); + } + if (first_chunk) { + op.read(0, cct->_conf->rgw_max_chunk_size, first_chunk, NULL); + } + bufferlist outbl; + r = rados_obj.operate(&op, &outbl); + + if (epoch) { + *epoch = rados_obj.get_last_version(); + } + + if (r < 0) + return r; + + if (psize) + *psize = size; + if (pmtime) + *pmtime = ceph::real_clock::from_timespec(mtime_ts); + if (attrs) { + filter_attrset(unfiltered_attrset, RGW_ATTR_PREFIX, attrs); + } + + return 0; +} + +int RGWSI_SysObj::stat(RGWSysObjectCtx& obj_ctx, + RGWSI_SysObj::SystemObject::Read::GetObjState& state, + rgw_raw_obj& obj, + map<string, bufferlist> *attrs, + real_time *lastmod, + uint64_t *obj_size, + RGWObjVersionTracker *objv_tracker) +{ + RGWSysObjState *astate = NULL; + + int r = get_system_obj_state(&obj_ctx, obj, &astate, objv_tracker); + if (r < 0) + return r; + + if (!astate->exists) { + return -ENOENT; + } + + if (attrs) { + *attrs = astate->attrset; + if (cct->_conf->subsys.should_gather<ceph_subsys_rgw, 20>()) { + map<string, bufferlist>::iterator iter; + for (iter = attrs->begin(); iter != attrs->end(); ++iter) { + ldout(cct, 20) << "Read xattr: " << iter->first << dendl; + } + } + } + + if (obj_size) + *obj_size = astate->size; + if (lastmod) + *lastmod = astate->mtime; + + return 0; +} + +int RGWSI_SysObj::read_obj(RGWObjectCtx& obj_ctx, + Obj::Read::GetObjState& read_state, + RGWObjVersionTracker *objv_tracker, + rgw_raw_obj& obj, + bufferlist *bl, off_t ofs, off_t end, + map<string, bufferlist> *attrs, + boost::optional<obj_version>) +{ + uint64_t len; + librados::ObjectReadOperation op; + + if (end < 0) + len = 0; + else + len = end - ofs + 1; + + if (objv_tracker) { + objv_tracker->prepare_op_for_read(&op); + } + + ldout(cct, 20) << "rados->read ofs=" << ofs << " len=" << len << dendl; + op.read(ofs, len, bl, NULL); + + if (attrs) { + op.getxattrs(attrs, NULL); + } + + RGWSI_Rados::Obj rados_obj; + int r = get_rados_obj(obj, &rados_obj); + if (r < 0) { + ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl; + return r; + } + r = rados_obj.operate(&op, NULL); + if (r < 0) { + ldout(cct, 20) << "rados_obj.operate() r=" << r << " bl.length=" << bl->length() << dendl; + return r; + } + ldout(cct, 20) << "rados_obj.operate() r=" << r << " bl.length=" << bl->length() << dendl; + + uint64_t op_ver = rados_obj.get_last_version(); + + if (read_state.last_ver > 0 && + read_state.last_ver != op_ver) { + ldout(cct, 5) << "raced with an object write, abort" << dendl; + return -ECANCELED; + } + + read_state.last_ver = op_ver; + + return bl.length(); +} + +/** + * Get an attribute for a system object. + * obj: the object to get attr + * name: name of the attr to retrieve + * dest: bufferlist to store the result in + * Returns: 0 on success, -ERR# otherwise. + */ +int RGWSI_SysObj::get_attr(rgw_raw_obj& obj, std::string_view name, bufferlist *dest) +{ + RGWSI_Rados::Obj rados_obj; + int r = get_rados_obj(obj, &rados_obj); + if (r < 0) { + ldout(cct, 20) << "get_rados_obj() on obj=" << obj << " returned " << r << dendl; + return r; + } + + librados::ObjectReadOperation op; + + int rval; + op.getxattr(name, dest, &rval); + + r = rados_obj.operate(&op, nullptr); + if (r < 0) + return r; + + return 0; +} + +void RGWSI_SysObj::Obj::invalidate_state() +{ + ctx.invalidate(obj); +} + +int RGWSI_SysObj::Obj::Read::GetObjState::get_rados_obj(RGWSI_RADOS *rados_svc, + RGWSI_Zone *zone_svc, + rgw_raw_obj& obj, + RGWSI_Rados::Obj **pobj) +{ + if (!has_rados_obj) { + zone_svc->canonicalize_raw_obj(&obj); + + rados_obj = rados_svc->obj(obj); + int r = rados_obj.open(); + if (r < 0) { + return r; + } + has_rados_obj = true; + } + *pobj = &rados_obj; + return 0; +} + +int RGWSI_SysObj::Obj::Read::stat() +{ + RGWSI_SysObj *svc = source.sysobj_svc; + rgw_raw_obj& obj = source.obj; + + return sysobj_svc->stat(source.ctx(), state, obj, stat_params.attrs, + stat_params.lastmod, stat_params.obj_size, + stat_params.objv_tracker); +} + + +int RGWSI_SysObj::Obj::Read::read(int64_t ofs, int64_t end, bufferlist *bl) +{ + RGWSI_SysObj *svc = source.sysobj_svc; + rgw_raw_obj& obj = source.get_obj(); + + return svc->read(source.get_ctx(), state, + read_params.objv_tracker, + obj, bl, ofs, end, + read_params.attrs, + refresh_version); +} + +int RGWSI_SysObj::Obj::Read::get_attr(std::string_view name, bufferlist *dest) +{ + RGWSI_SysObj *svc = source.sysobj_svc; + rgw_raw_obj& obj = source.get_obj(); + + return svc->get_attr(obj, name, dest); +} + diff --git a/src/rgw/services/svc_sys_obj.h b/src/rgw/services/svc_sys_obj.h new file mode 100644 index 00000000000..1a38cc268f4 --- /dev/null +++ b/src/rgw/services/svc_sys_obj.h @@ -0,0 +1,269 @@ +#ifndef CEPH_RGW_SERVICES_SYS_OBJ_H +#define CEPH_RGW_SERVICES_SYS_OBJ_H + + +#include "rgw/rgw_service.h" + +#include "svc_rados.h" + + +class RGWSI_Zone; +class RGWSI_SysObj; + +struct RGWSysObjState { + rgw_raw_obj obj; + bool has_attrs{false}; + bool exists{false}; + uint64_t size{0}; + ceph::real_time mtime; + uint64_t epoch{0}; + bufferlist obj_tag; + bool has_data{false}; + bufferlist data; + bool prefetch_data{false}; + uint64_t pg_ver{0}; + + /* important! don't forget to update copy constructor */ + + RGWObjVersionTracker objv_tracker; + + map<string, bufferlist> attrset; + RGWSysObjState() {} + RGWSysObjState(const RGWSysObjState& rhs) : obj (rhs.obj) { + has_attrs = rhs.has_attrs; + exists = rhs.exists; + size = rhs.size; + mtime = rhs.mtime; + epoch = rhs.epoch; + if (rhs.obj_tag.length()) { + obj_tag = rhs.obj_tag; + } + has_data = rhs.has_data; + if (rhs.data.length()) { + data = rhs.data; + } + prefetch_data = rhs.prefetch_data; + pg_ver = rhs.pg_ver; + objv_tracker = rhs.objv_tracker; + } +}; + +template <class T, class S> +class RGWSysObjectCtxImpl { + RGWSI_SysObj *sysobj_svc; + std::map<T, S> objs_state; + RWLock lock; + +public: + explicit RGWSysObjectCtxImpl(RGWSI_SysObj *_sysobj_svc) : sysobj_svc(_sysobj_svc), lock("RGWSysObjectCtxImpl") {} + + RGWSysObjectCtxImpl(const RGWSysObjectCtxImpl& rhs) : sysobj_svc(rhs.sysobj_svc), + objs_state(rhs.objs_state), + lock("RGWSysObjectCtxImpl") {} + RGWSysObjectCtxImpl(const RGWSysObjectCtxImpl&& rhs) : sysobj_svc(rhs.sysobj_svc), + objs_state(std::move(rhs.objs_state)), + lock("RGWSysObjectCtxImpl") {} + + S *get_state(const T& obj) { + S *result; + typename std::map<T, S>::iterator iter; + lock.get_read(); + assert (!obj.empty()); + iter = objs_state.find(obj); + if (iter != objs_state.end()) { + result = &iter->second; + lock.unlock(); + } else { + lock.unlock(); + lock.get_write(); + result = &objs_state[obj]; + lock.unlock(); + } + return result; + } + + void set_atomic(T& obj) { + RWLock::WLocker wl(lock); + assert (!obj.empty()); + objs_state[obj].is_atomic = true; + } + void set_prefetch_data(T& obj) { + RWLock::WLocker wl(lock); + assert (!obj.empty()); + objs_state[obj].prefetch_data = true; + } + void invalidate(T& obj) { + RWLock::WLocker wl(lock); + auto iter = objs_state.find(obj); + if (iter == objs_state.end()) { + return; + } + bool is_atomic = iter->second.is_atomic; + bool prefetch_data = iter->second.prefetch_data; + + objs_state.erase(iter); + + if (is_atomic || prefetch_data) { + auto& s = objs_state[obj]; + s.is_atomic = is_atomic; + s.prefetch_data = prefetch_data; + } + } +}; + +using RGWSysObjectCtx = RGWSysObjectCtxImpl<rgw_raw_obj, RGWSysObjState>; + +class RGWS_SysObj : public RGWService +{ +public: + RGWS_SysObj(CephContext *cct) : RGWService(cct, "sys_obj") {} + + int create_instance(const std::string& conf, RGWServiceInstanceRef *instance) override; +}; + +class RGWSI_SysObj : public RGWServiceInstance +{ +public: + class Obj { + friend class Read; + + RGWSI_SysObj *sysobj_svc; + RGWSysObjectCtx& ctx; + rgw_raw_obj obj; + + RGWSI_RADOS *get_rados_svc(); + + public: + Obj(RGWSI_SysObj *_sysobj_svc, + RGWSysObjectCtx& _ctx, + const rgw_raw_obj& _obj) : sysobj_svc(_sysobj_svc), + ctx(_ctx), + obj(_obj) {} + + void invalidate_state(); + + RGWSysObjectCtx& get_ctx() { + return ctx; + } + + rgw_raw_obj& get_obj() { + return obj; + } + + struct Read { + Obj& source; + + struct GetObjState { + RGWSI_RADOS::Obj rados_obj; + bool has_rados_obj{false}; + uint64_t last_ver{0}; + + GetObjState() {} + + int get_rados_obj(RGWSI_SysObj *sysobj_svc, rgw_raw_obj& obj, RGWSI_RADOS::Obj **pobj); + } state; + + struct StatParams { + RGWObjVersionTracker *objv_tracker{nullptr}; + ceph::real_time *lastmod{nullptr}; + uint64_t *obj_size{nullptr}; + map<string, bufferlist> *attrs{nullptr}; + + StatParams& set_last_mod(ceph::real_time *_lastmod) { + lastmod = _lastmod; + return *this; + } + StatParams& set_obj_size(uint64_t *_obj_size) { + obj_size = _obj_size; + return *this; + } + StatParams& set_attrs(map<string, bufferlist> *_attrs) { + attrs = _attrs; + return *this; + } + } stat_params; + + struct ReadParams { + RGWObjVersionTracker *objv_tracker{nullptr}; + map<string, bufferlist> *attrs{nullptr}; + boost::optional<obj_version> refresh_version{boost::none}; + + ReadParams& set_attrs(map<string, bufferlist> *_attrs) { + attrs = _attrs; + return *this; + } + ReadParams& set_obj_tracker(RGWObjVersionTracker *_objv_tracker) { + objv_tracker = _objv_tracker; + return *this; + } + ReadParams& set_refresh_version(const obj_version& rf) { + refresh_version = rf; + return *this; + } + } read_params; + + Read(Obj& _source) : source(_source) {} + + int stat(); + int read(int64_t ofs, int64_t end, bufferlist *pbl); + int read(bufferlist *pbl) { + return read(0, -1, pbl); + } + int get_attr(std::string_view name, bufferlist *dest); + }; + }; + + friend class Obj; + friend class Obj::Read; + +private: + std::shared_ptr<RGWSI_RADOS> rados_svc; + std::shared_ptr<RGWSI_Zone> zone_svc; + + std::map<std::string, RGWServiceInstance::dependency> get_deps() override; + int load(const std::string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) override; + + int get_rados_obj(RGWSI_Zone *zone_svc, rgw_raw_obj& obj, RGWSI_RADOS::Obj *pobj); + + int get_system_obj_state_impl(RGWSysObjectCtx *rctx, rgw_raw_obj& obj, RGWSysObjState **state, RGWObjVersionTracker *objv_tracker); + int get_system_obj_state(RGWSysObjectCtx *rctx, rgw_raw_obj& obj, RGWSysObjState **state, RGWObjVersionTracker *objv_tracker); + + int raw_stat(rgw_raw_obj& obj, uint64_t *psize, real_time *pmtime, uint64_t *epoch, + map<string, bufferlist> *attrs, bufferlist *first_chunk, + RGWObjVersionTracker *objv_tracker); + + int stat(RGWSysObjectCtx& obj_ctx, + RGWSI_SysObj::Obj::Read::GetObjState& state, + rgw_raw_obj& obj, + map<string, bufferlist> *attrs, + real_time *lastmod, + uint64_t *obj_size, + RGWObjVersionTracker *objv_tracker); + + int read(RGWSysObjectCtx& obj_ctx, + Obj::Read::GetObjState& read_state, + RGWObjVersionTracker *objv_tracker, + rgw_raw_obj& obj, + bufferlist *bl, off_t ofs, off_t end, + map<string, bufferlist> *attrs, + boost::optional<obj_version>); + + int get_attr(rgw_raw_obj& obj, std::string_view name, bufferlist *dest); + +public: + RGWSI_SysObj(RGWService *svc, CephContext *cct): RGWServiceInstance(svc, cct) {} + + RGWSysObjectCtx&& init_obj_ctx() { + return std::move(RGWSysObjectCtx(this)); + } + + Obj&& get_obj(RGWSysObjectCtx& obj_ctx, const rgw_raw_obj& obj) { + return std::move(Obj(this, obj_ctx, obj)); + } + +}; + +using RGWSysObj = RGWSI_SysObj::Obj; + +#endif + diff --git a/src/rgw/services/svc_zone.cc b/src/rgw/services/svc_zone.cc index 22e516d9438..ab9f63031f3 100644 --- a/src/rgw/services/svc_zone.cc +++ b/src/rgw/services/svc_zone.cc @@ -1,7 +1,26 @@ #include "svc_zone.h" #include "svc_rados.h" +#include "svc_sys_obj.h" #include "rgw/rgw_zone.h" +#include "rgw/rgw_rest_conn.h" + +#include "common/errno.h" + +#define dout_subsys ceph_subsys_rgw + +static string zone_names_oid_prefix = "zone_names."; +static string region_info_oid_prefix = "region_info."; +static string realm_names_oid_prefix = "realms_names."; +static string default_region_info_oid = "default.region"; +static string region_map_oid = "region_map"; +const string default_zonegroup_name = "default"; +const string default_zone_name = "default"; +static string zonegroup_names_oid_prefix = "zonegroups_names."; +static string RGW_DEFAULT_ZONE_ROOT_POOL = "rgw.root"; +static string RGW_DEFAULT_ZONEGROUP_ROOT_POOL = "rgw.root"; +static string RGW_DEFAULT_REALM_ROOT_POOL = "rgw.root"; +static string RGW_DEFAULT_PERIOD_ROOT_POOL = "rgw.root"; int RGWS_Zone::create_instance(const string& conf, RGWServiceInstanceRef *instance) { @@ -11,17 +30,692 @@ int RGWS_Zone::create_instance(const string& conf, RGWServiceInstanceRef *instan std::map<string, RGWServiceInstance::dependency> RGWSI_Zone::get_deps() { - RGWServiceInstance::dependency dep = { .name = "rados", - .conf = "{}" }; + RGWServiceInstance::dependency dep1 = { .name = "rados", + .conf = "{}" }; + RGWServiceInstance::dependency dep2 = { .name = "sys_obj", + .conf = "{}" }; map<string, RGWServiceInstance::dependency> deps; - deps["rados_dep"] = dep; + deps["rados_dep"] = dep1; + deps["sys_obj_dep"] = dep2; return deps; } -int RGWSI_Zone::init(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) +int RGWSI_Zone::load(const string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) { rados_svc = static_pointer_cast<RGWSI_RADOS>(dep_refs["rados_dep"]); assert(rados_svc); + + sysobj_svc = static_pointer_cast<RGWSI_SysObj>(dep_refs["sys_obj_dep"]); + assert(sysobj_svc); + + realm = make_shared<RGWRealm>(); + zonegroup = make_shared<RGWZoneGroup>(); + zone_public_config = make_shared<RGWZone>(); + zone_params = make_shared<RGWZoneParams>(); + current_period = make_shared<RGWPeriod>(); + + return 0; +} + +int RGWSI_Zone::init() +{ + int ret = realm->init(cct, sysobj_svc.get()); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << "failed reading realm info: ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } else if (ret != -ENOENT) { + ldout(cct, 20) << "realm " << realm->get_name() << " " << realm->get_id() << dendl; + ret = current_period->init(cct, sysobj_svc.get(), realm->get_id(), realm->get_name()); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << "failed reading current period info: " << " " << cpp_strerror(-ret) << dendl; + return ret; + } + ldout(cct, 20) << "current period " << current_period->get_id() << dendl; + } + + ret = replace_region_with_zonegroup(); + if (ret < 0) { + lderr(cct) << "failed converting region to zonegroup : ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } + + ret = convert_regionmap(); + if (ret < 0) { + lderr(cct) << "failed converting regionmap: " << cpp_strerror(-ret) << dendl; + return ret; + } + + bool zg_initialized = false; + + if (!current_period->get_id().empty()) { + ret = init_zg_from_period(&zg_initialized); + if (ret < 0) { + return ret; + } + } + + bool creating_defaults = false; + bool using_local = (!zg_initialized); + if (using_local) { + ldout(cct, 10) << " cannot find current period zonegroup using local zonegroup" << dendl; + ret = init_zg_from_local(&creating_defaults); + if (ret < 0) { + return ret; + } + // read period_config into current_period + auto& period_config = current_period->get_config(); + ret = period_config.read(sysobj_svc.get(), zonegroup->realm_id); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << "ERROR: failed to read period config: " + << cpp_strerror(ret) << dendl; + return ret; + } + } + + ldout(cct, 10) << "Cannot find current period zone using local zone" << dendl; + if (creating_defaults && cct->_conf->rgw_zone.empty()) { + ldout(cct, 10) << " Using default name "<< default_zone_name << dendl; + zone_params->set_name(default_zone_name); + } + + ret = zone_params->init(cct, sysobj_svc.get()); + if (ret < 0 && ret != -ENOENT) { + lderr(cct) << "failed reading zone info: ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } + map<string, RGWZone>::iterator zone_iter = get_zonegroup().zones.find(zone_params->get_id()); + if (zone_iter == get_zonegroup().zones.end()) { + if (using_local) { + lderr(cct) << "Cannot find zone id=" << zone_params->get_id() << " (name=" << zone_params->get_name() << ")" << dendl; + return -EINVAL; + } + ldout(cct, 1) << "Cannot find zone id=" << zone_params->get_id() << " (name=" << zone_params->get_name() << "), switching to local zonegroup configuration" << dendl; + ret = init_zg_from_local(&creating_defaults); + if (ret < 0) { + return ret; + } + zone_iter = get_zonegroup().zones.find(zone_params->get_id()); + } + if (zone_iter != get_zonegroup().zones.end()) { + *zone_public_config = zone_iter->second; + ldout(cct, 20) << "zone " << zone_params->get_name() << dendl; + } else { + lderr(cct) << "Cannot find zone id=" << zone_params->get_id() << " (name=" << zone_params->get_name() << ")" << dendl; + return -EINVAL; + } + + zone_short_id = current_period->get_map().get_zone_short_id(zone_params->get_id()); + + writeable_zone = (zone_public_config->tier_type.empty() || zone_public_config->tier_type == "rgw"); + + return 0; +} + +void RGWSI_Zone::shutdown() +{ + delete rest_master_conn; + + map<string, RGWRESTConn *>::iterator iter; + for (iter = zone_conn_map.begin(); iter != zone_conn_map.end(); ++iter) { + RGWRESTConn *conn = iter->second; + delete conn; + } + + for (iter = zonegroup_conn_map.begin(); iter != zonegroup_conn_map.end(); ++iter) { + RGWRESTConn *conn = iter->second; + delete conn; + } +} + +int RGWSI_Zone::list_regions(list<string>& regions) +{ + RGWZoneGroup zonegroup; + + return list_raw_prefixed_objs(zonegroup.get_pool(cct), region_info_oid_prefix, regions); +} + +int RGWSI_Zone::list_zonegroups(list<string>& zonegroups) +{ + RGWZoneGroup zonegroup; + + return list_raw_prefixed_objs(zonegroup.get_pool(cct), zonegroup_names_oid_prefix, zonegroups); +} + +int RGWSI_Zone::list_zones(list<string>& zones) +{ + RGWZoneParams zoneparams; + + return list_raw_prefixed_objs(zoneparams.get_pool(cct), zone_names_oid_prefix, zones); +} + +int RGWSI_Zone::list_realms(list<string>& realms) +{ + RGWRealm realm(cct, sysobj_svc.get()); + return list_raw_prefixed_objs(realm.get_pool(cct), realm_names_oid_prefix, realms); +} + +int RGWSI_Zone::list_periods(list<string>& periods) +{ + RGWPeriod period; + list<string> raw_periods; + int ret = list_raw_prefixed_objs(period.get_pool(cct), period.get_info_oid_prefix(), raw_periods); + if (ret < 0) { + return ret; + } + for (const auto& oid : raw_periods) { + size_t pos = oid.find("."); + if (pos != std::string::npos) { + periods.push_back(oid.substr(0, pos)); + } else { + periods.push_back(oid); + } + } + periods.sort(); // unique() only detects duplicates if they're adjacent + periods.unique(); + return 0; +} + + +int RGWSI_Zone::list_periods(const string& current_period, list<string>& periods) +{ + int ret = 0; + string period_id = current_period; + while(!period_id.empty()) { + RGWPeriod period(period_id); + ret = period.init(cct, sysobj_svc.get()); + if (ret < 0) { + return ret; + } + periods.push_back(period.get_id()); + period_id = period.get_predecessor(); + } + + return ret; +} + +/** + * Replace all region configuration with zonegroup for + * backward compatability + * Returns 0 on success, -ERR# on failure. + */ +int RGWSI_Zone::replace_region_with_zonegroup() +{ + /* copy default region */ + /* convert default region to default zonegroup */ + string default_oid = cct->_conf->rgw_default_region_info_oid; + if (default_oid.empty()) { + default_oid = default_region_info_oid; + } + + RGWZoneGroup default_zonegroup; + rgw_pool pool{default_zonegroup.get_pool(cct)}; + string oid = "converted"; + bufferlist bl; + + RGWSysObjectCtx obj_ctx = sysobj_svc->init_obj_ctx(); + RGWSysObj sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid)); + RGWSysObj::Read rop(sysobj); + + int ret = rop.read(&bl); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << __func__ << " failed to read converted: ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } else if (ret != -ENOENT) { + ldout(cct, 20) << "System already converted " << dendl; + return 0; + } + + string default_region; + ret = default_zonegroup.init(cct, sysobj_svc.get(), false, true); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed init default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = default_zonegroup.read_default_id(default_region, true); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << __func__ << " failed reading old default region: ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } + + /* convert regions to zonegroups */ + list<string> regions; + ret = list_regions(regions); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << __func__ << " failed to list regions: ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } else if (ret == -ENOENT || regions.empty()) { + RGWZoneParams zoneparams(default_zone_name); + int ret = zoneparams.init(cct, sysobj_svc.get()); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << __func__ << ": error initializing default zone params: " << cpp_strerror(-ret) << dendl; + return ret; + } + /* update master zone */ + RGWZoneGroup default_zg(default_zonegroup_name); + ret = default_zg.init(cct, sysobj_svc.get()); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << __func__ << ": error in initializing default zonegroup: " << cpp_strerror(-ret) << dendl; + return ret; + } + if (ret != -ENOENT && default_zg.master_zone.empty()) { + default_zg.master_zone = zoneparams.get_id(); + return default_zg.update(); + } + return 0; + } + + string master_region, master_zone; + for (list<string>::iterator iter = regions.begin(); iter != regions.end(); ++iter) { + if (*iter != default_zonegroup_name){ + RGWZoneGroup region(*iter); + int ret = region.init(cct, sysobj_svc.get(), true, true); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed init region "<< *iter << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + if (region.is_master_zonegroup()) { + master_region = region.get_id(); + master_zone = region.master_zone; + } + } + } + + /* create realm if there is none. + The realm name will be the region and zone concatenated + realm id will be mds of its name */ + if (realm->get_id().empty() && !master_region.empty() && !master_zone.empty()) { + string new_realm_name = master_region + "." + master_zone; + unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE]; + char md5_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; + MD5 hash; + hash.Update((const unsigned char *)new_realm_name.c_str(), new_realm_name.length()); + hash.Final(md5); + buf_to_hex(md5, CEPH_CRYPTO_MD5_DIGESTSIZE, md5_str); + string new_realm_id(md5_str); + RGWRealm new_realm(new_realm_id,new_realm_name); + ret = new_realm.init(cct, sysobj_svc.get(), false); + if (ret < 0) { + ldout(cct, 0) << __func__ << " Error initing new realm: " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = new_realm.create(); + if (ret < 0 && ret != -EEXIST) { + ldout(cct, 0) << __func__ << " Error creating new realm: " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = new_realm.set_as_default(); + if (ret < 0) { + ldout(cct, 0) << __func__ << " Error setting realm as default: " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = realm.init(cct, this); + if (ret < 0) { + ldout(cct, 0) << __func__ << " Error initing realm: " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = current_period->init(cct, this, realm->get_id(), realm->get_name()); + if (ret < 0) { + ldout(cct, 0) << __func__ << " Error initing current period: " << cpp_strerror(-ret) << dendl; + return ret; + } + } + + list<string>::iterator iter; + /* create zonegroups */ + for (iter = regions.begin(); iter != regions.end(); ++iter) + { + ldout(cct, 0) << __func__ << " Converting " << *iter << dendl; + /* check to see if we don't have already a zonegroup with this name */ + RGWZoneGroup new_zonegroup(*iter); + ret = new_zonegroup.init(cct , sysobj_svc.get()); + if (ret == 0 && new_zonegroup.get_id() != *iter) { + ldout(cct, 0) << __func__ << " zonegroup "<< *iter << " already exists id " << new_zonegroup.get_id () << + " skipping conversion " << dendl; + continue; + } + RGWZoneGroup zonegroup(*iter); + zonegroup.set_id(*iter); + int ret = zonegroup.init(cct, this, true, true); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed init zonegroup: ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } + zonegroup.realm_id = realm->get_id(); + /* fix default region master zone */ + if (*iter == default_zonegroup_name && zonegroup.master_zone.empty()) { + ldout(cct, 0) << __func__ << " Setting default zone as master for default region" << dendl; + zonegroup.master_zone = default_zone_name; + } + ret = zonegroup.update(); + if (ret < 0 && ret != -EEXIST) { + ldout(cct, 0) << __func__ << " failed to update zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } + ret = zonegroup.update_name(); + if (ret < 0 && ret != -EEXIST) { + ldout(cct, 0) << __func__ << " failed to update_name for zonegroup " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } + if (zonegroup.get_name() == default_region) { + ret = zonegroup.set_as_default(); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed to set_as_default " << *iter << ": ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } + } + for (map<string, RGWZone>::const_iterator iter = zonegroup.zones.begin(); iter != zonegroup.zones.end(); + ++iter) { + ldout(cct, 0) << __func__ << " Converting zone" << iter->first << dendl; + RGWZoneParams zoneparams(iter->first, iter->first); + zoneparams.set_id(iter->first); + zoneparams.realm_id = realm->get_id(); + ret = zoneparams.init(cct, sysobj_svc.get()); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << __func__ << " failed to init zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl; + return ret; + } else if (ret == -ENOENT) { + ldout(cct, 0) << __func__ << " zone is part of another cluster " << iter->first << " skipping " << dendl; + continue; + } + zonegroup.realm_id = realm->get_id(); + ret = zoneparams.update(); + if (ret < 0 && ret != -EEXIST) { + ldout(cct, 0) << __func__ << " failed to update zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = zoneparams.update_name(); + if (ret < 0 && ret != -EEXIST) { + ldout(cct, 0) << __func__ << " failed to init zoneparams " << iter->first << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + } + + if (!current_period->get_id().empty()) { + ret = current_period->add_zonegroup(zonegroup); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed to add zonegroup to current_period: " << cpp_strerror(-ret) << dendl; + return ret; + } + } + } + + if (!current_period->get_id().empty()) { + ret = current_period->update(); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed to update new period: " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = current_period->store_info(false); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed to store new period: " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = current_period->reflect(); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed to update local objects: " << cpp_strerror(-ret) << dendl; + return ret; + } + } + + for (auto const& iter : regions) { + RGWZoneGroup zonegroup(iter); + int ret = zonegroup.init(cct, this, true, true); + if (ret < 0) { + ldout(cct, 0) << __func__ << " failed init zonegroup" << iter << ": ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = zonegroup.delete_obj(true); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << __func__ << " failed to delete region " << iter << ": ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } + } + + /* mark as converted */ + ret = rgw_put_system_obj(this, pool, oid, bl, + true, NULL, real_time(), NULL); + if (ret < 0 ) { + ldout(cct, 0) << __func__ << " failed to mark cluster as converted: ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } + + return 0; +} + +/** + * Add new connection to connections map + * @param zonegroup_conn_map map which new connection will be added to + * @param zonegroup zonegroup which new connection will connect to + * @param new_connection pointer to new connection instance + */ +static void add_new_connection_to_map(map<string, RGWRESTConn *> &zonegroup_conn_map, + const RGWZoneGroup &zonegroup, RGWRESTConn *new_connection) +{ + // Delete if connection is already exists + map<string, RGWRESTConn *>::iterator iterZoneGroup = zonegroup_conn_map.find(zonegroup.get_id()); + if (iterZoneGroup != zonegroup_conn_map.end()) { + delete iterZoneGroup->second; + } + + // Add new connection to connections map + zonegroup_conn_map[zonegroup.get_id()] = new_connection; +} + +int RGWSI_Zone::init_zg_from_period(bool *initialized) +{ + *initialized = false; + + if (current_period->get_id().empty()) { + return 0; + } + + int ret = zonegroup->init(cct, sysobj_svc.get()); + ldout(cct, 20) << "period zonegroup init ret " << ret << dendl; + if (ret == -ENOENT) { + return 0; + } + if (ret < 0) { + ldout(cct, 0) << "failed reading zonegroup info: " << cpp_strerror(-ret) << dendl; + return ret; + } + ldout(cct, 20) << "period zonegroup name " << zonegroup->get_name() << dendl; + + map<string, RGWZoneGroup>::const_iterator iter = + current_period->get_map().zonegroups.find(zonegroup->get_id()); + + if (iter != current_period->get_map().zonegroups.end()) { + ldout(cct, 20) << "using current period zonegroup " << zonegroup->get_name() << dendl; + *zonegroup = iter->second; + ret = zonegroup->init(cct, sysobj_svc.get(), false); + if (ret < 0) { + ldout(cct, 0) << "failed init zonegroup: " << " " << cpp_strerror(-ret) << dendl; + return ret; + } + ret = zone_params->init(cct, sysobj_svc.get()); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl; + return ret; + } if (ret ==-ENOENT && zonegroup->get_name() == default_zonegroup_name) { + ldout(cct, 10) << " Using default name "<< default_zone_name << dendl; + zone_params->set_name(default_zone_name); + ret = zone_params->init(cct, sysobj_svc.get()); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << "failed reading zone params info: " << " " << cpp_strerror(-ret) << dendl; + return ret; + } + } + } + for (iter = current_period->get_map().zonegroups.begin(); + iter != current_period->get_map().zonegroups.end(); ++iter){ + const RGWZoneGroup& zg = iter->second; + // use endpoints from the zonegroup's master zone + auto master = zg.zones.find(zg.master_zone); + if (master == zg.zones.end()) { + // fix missing master zone for a single zone zonegroup + if (zg.master_zone.empty() && zg.zones.size() == 1) { + master = zg.zones.begin(); + ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing master_zone, setting zone " << + master->second.name << " id:" << master->second.id << " as master" << dendl; + if (zonegroup->get_id() == zg.get_id()) { + zonegroup->master_zone = master->second.id; + ret = zonegroup->update(); + if (ret < 0) { + ldout(cct, 0) << "error updating zonegroup : " << cpp_strerror(-ret) << dendl; + return ret; + } + } else { + RGWZoneGroup fixed_zg(zg.get_id(),zg.get_name()); + ret = fixed_zg.init(cct, sysobj_svc.get()); + if (ret < 0) { + ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl; + return ret; + } + fixed_zg.master_zone = master->second.id; + ret = fixed_zg.update(); + if (ret < 0) { + ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl; + return ret; + } + } + } else { + ldout(cct, 0) << "zonegroup " << zg.get_name() << " missing zone for master_zone=" << + zg.master_zone << dendl; + return -EINVAL; + } + } + const auto& endpoints = master->second.endpoints; + add_new_connection_to_map(zonegroup_conn_map, zg, new RGWRESTConn(cct, this, zg.get_id(), endpoints)); + if (!current_period->get_master_zonegroup().empty() && + zg.get_id() == current_period->get_master_zonegroup()) { + rest_master_conn = new RGWRESTConn(cct, this, zg.get_id(), endpoints); + } + } + + *initialized = true; + + return 0; +} + +int RGWSI_Zone::init_zg_from_local(bool *creating_defaults) +{ + int ret = zonegroup->init(cct, sysobj_svc.get()); + if ( (ret < 0 && ret != -ENOENT) || (ret == -ENOENT && !cct->_conf->rgw_zonegroup.empty())) { + ldout(cct, 0) << "failed reading zonegroup info: ret "<< ret << " " << cpp_strerror(-ret) << dendl; + return ret; + } else if (ret == -ENOENT) { + *creating_defaults = true; + ldout(cct, 10) << "Creating default zonegroup " << dendl; + ret = zonegroup->create_default(); + if (ret < 0) { + ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } + ret = zonegroup->init(cct, sysobj_svc.get()); + if (ret < 0) { + ldout(cct, 0) << "failure in zonegroup create_default: ret "<< ret << " " << cpp_strerror(-ret) + << dendl; + return ret; + } + } + ldout(cct, 20) << "zonegroup " << zonegroup->get_name() << dendl; + if (zonegroup->is_master_zonegroup()) { + // use endpoints from the zonegroup's master zone + auto master = zonegroup->zones.find(zonegroup->master_zone); + if (master == zonegroup->zones.end()) { + // fix missing master zone for a single zone zonegroup + if (zonegroup->master_zone.empty() && zonegroup->zones.size() == 1) { + master = zonegroup->zones.begin(); + ldout(cct, 0) << "zonegroup " << zonegroup->get_name() << " missing master_zone, setting zone " << + master->second.name << " id:" << master->second.id << " as master" << dendl; + zonegroup->master_zone = master->second.id; + ret = zonegroup->update(); + if (ret < 0) { + ldout(cct, 0) << "error initializing zonegroup : " << cpp_strerror(-ret) << dendl; + return ret; + } + } else { + ldout(cct, 0) << "zonegroup " << zonegroup->get_name() << " missing zone for " + "master_zone=" << zonegroup->master_zone << dendl; + return -EINVAL; + } + } + const auto& endpoints = master->second.endpoints; + rest_master_conn = new RGWRESTConn(cct, this, zonegroup->get_id(), endpoints); + } + + return 0; +} + +int RGWSI_Zone::convert_regionmap() +{ + RGWZoneGroupMap zonegroupmap; + + string pool_name = cct->_conf->rgw_zone_root_pool; + if (pool_name.empty()) { + pool_name = RGW_DEFAULT_ZONE_ROOT_POOL; + } + string oid = region_map_oid; + + rgw_pool pool(pool_name); + bufferlist bl; + + RGWSysObjectCtx obj_ctx = sysobj_svc->init_obj_ctx(); + RGWSysObj sysobj = sysobj_svc->get_obj(obj_ctx, rgw_raw_obj(pool, oid)); + RGWSysObj::Read rop(sysobj); + + int ret = rop.read(&bl); + if (ret < 0 && ret != -ENOENT) { + return ret; + } else if (ret == -ENOENT) { + return 0; + } + + try { + auto iter = bl.cbegin(); + decode(zonegroupmap, iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "error decoding regionmap from " << pool << ":" << oid << dendl; + return -EIO; + } + + for (map<string, RGWZoneGroup>::iterator iter = zonegroupmap.zonegroups.begin(); + iter != zonegroupmap.zonegroups.end(); ++iter) { + RGWZoneGroup& zonegroup = iter->second; + ret = zonegroup.init(cct, sysobj_svc.get(), false); + ret = zonegroup.update(); + if (ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << "Error could not update zonegroup " << zonegroup.get_name() << ": " << + cpp_strerror(-ret) << dendl; + return ret; + } else if (ret == -ENOENT) { + ret = zonegroup.create(); + if (ret < 0) { + ldout(cct, 0) << "Error could not create " << zonegroup.get_name() << ": " << + cpp_strerror(-ret) << dendl; + return ret; + } + } + } + + current_period->set_user_quota(zonegroupmap.user_quota); + current_period->set_bucket_quota(zonegroupmap.bucket_quota); + + // remove the region_map so we don't try to convert again + rgw_raw_obj obj(pool, oid); + ret = delete_system_obj(obj); + if (ret < 0) { + ldout(cct, 0) << "Error could not remove " << obj + << " after upgrading to zonegroup map: " << cpp_strerror(ret) << dendl; + return ret; + } + return 0; } @@ -160,3 +854,11 @@ bool RGWSI_Zone::can_reshard() const (zonegroup->zones.size() == 1 && current_period->is_single_zonegroup()); } + +void RGWSI_Zone::canonicalize_raw_obj(rgw_raw_obj *obj) +{ + if (obj->oid.empty()) { + obj->oid = obj->pool.to_str(); + obj->pool = zone_params->domain_root; + } +} diff --git a/src/rgw/services/svc_zone.h b/src/rgw/services/svc_zone.h index 1304c2475da..646d9084b9a 100644 --- a/src/rgw/services/svc_zone.h +++ b/src/rgw/services/svc_zone.h @@ -3,16 +3,11 @@ #include "rgw/rgw_service.h" +#include "rgw/rgw_zone.h" class RGWSI_RADOS; - -struct RGWZoneGroup; -struct RGWZone; -struct RGWZoneParams; -struct RGWPeriod; -struct RGWRealm; -struct RGWZonePlacementInfo; +class RGWSI_SysObj; class RGWRESTConn; @@ -21,12 +16,13 @@ class RGWS_Zone : public RGWService public: RGWS_Zone(CephContext *cct) : RGWService(cct, "zone") {} - int create_instance(const std::string& conf, RGWServiceInstanceRef *instance); + int create_instance(const std::string& conf, RGWServiceInstanceRef *instance) override; }; class RGWSI_Zone : public RGWServiceInstance { std::shared_ptr<RGWSI_RADOS> rados_svc; + std::shared_ptr<RGWSI_SysObj> sysobj_svc; std::shared_ptr<RGWRealm> realm; std::shared_ptr<RGWZoneGroup> zonegroup; @@ -36,9 +32,6 @@ class RGWSI_Zone : public RGWServiceInstance uint32_t zone_short_id{0}; bool writeable_zone{false}; - std::map<std::string, RGWServiceInstance::dependency> get_deps(); - int init(const std::string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs); - RGWRESTConn *rest_master_conn{nullptr}; map<string, RGWRESTConn *> zone_conn_map; map<string, RGWRESTConn *> zone_data_sync_from_map; @@ -48,6 +41,16 @@ class RGWSI_Zone : public RGWServiceInstance map<string, string> zone_id_by_name; map<string, RGWZone> zone_by_id; + std::map<std::string, RGWServiceInstance::dependency> get_deps() override; + int load(const std::string& conf, std::map<std::string, RGWServiceInstanceRef>& dep_refs) override; + int init() override; + void shutdown() override; + + int replace_region_with_zonegroup(); + int init_zg_from_period(bool *initialized); + int init_zg_from_local(bool *creating_defaults); + int convert_regionmap(); + public: RGWSI_Zone(RGWService *svc, CephContext *cct): RGWServiceInstance(svc, cct) {} @@ -77,6 +80,10 @@ public: return zone_conn_map; } + map<string, RGWRESTConn *>& get_zone_data_notify_to_map() { + return zone_data_notify_to_map; + } + bool find_zone_by_id(const string& id, RGWZone **zone); RGWRESTConn *get_zone_conn_by_id(const string& id); @@ -95,6 +102,13 @@ public: bool need_to_log_data() const; bool need_to_log_metadata() const; bool can_reshard() const; + + int list_zonegroups(list<string>& zonegroups); + int list_regions(list<string>& regions); + int list_zones(list<string>& zones); + int list_realms(list<string>& realms); + int list_periods(list<string>& periods); + int list_periods(const string& current_period, list<string>& periods); }; #endif |