From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:54:28 +0200 Subject: Adding upstream version 18.2.2. Signed-off-by: Daniel Baumann --- src/rgw/driver/json_config/store.cc | 177 ++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 src/rgw/driver/json_config/store.cc (limited to 'src/rgw/driver/json_config/store.cc') diff --git a/src/rgw/driver/json_config/store.cc b/src/rgw/driver/json_config/store.cc new file mode 100644 index 000000000..cf5adda25 --- /dev/null +++ b/src/rgw/driver/json_config/store.cc @@ -0,0 +1,177 @@ +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include +#include "include/buffer.h" +#include "common/errno.h" +#include "common/ceph_json.h" +#include "rgw_zone.h" +#include "driver/immutable_config/store.h" +#include "store.h" + +namespace rgw::sal { + +namespace { + +struct DecodedConfig { + RGWZoneGroup zonegroup; + RGWZoneParams zone; + RGWPeriodConfig period_config; + + void decode_json(JSONObj *obj) + { + JSONDecoder::decode_json("zonegroup", zonegroup, obj); + JSONDecoder::decode_json("zone", zone, obj); + JSONDecoder::decode_json("period_config", period_config, obj); + } +}; + +static void parse_config(const DoutPrefixProvider* dpp, const char* filename) +{ + bufferlist bl; + std::string errmsg; + int r = bl.read_file(filename, &errmsg); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to read json config file '" << filename + << "': " << errmsg << dendl; + throw std::system_error(-r, std::system_category()); + } + + JSONParser p; + if (!p.parse(bl.c_str(), bl.length())) { + ldpp_dout(dpp, 0) << "failed to parse json config file" << dendl; + throw std::system_error(make_error_code(std::errc::invalid_argument)); + } + + DecodedConfig config; + try { + decode_json_obj(config, &p); + } catch (const JSONDecoder::err& e) { + ldpp_dout(dpp, 0) << "failed to decode JSON input: " << e.what() << dendl; + throw std::system_error(make_error_code(std::errc::invalid_argument)); + } +} + +void sanity_check_config(const DoutPrefixProvider* dpp, DecodedConfig& config) +{ + if (config.zonegroup.id.empty()) { + config.zonegroup.id = "default"; + } + if (config.zonegroup.name.empty()) { + config.zonegroup.name = "default"; + } + if (config.zonegroup.api_name.empty()) { + config.zonegroup.api_name = config.zonegroup.name; + } + + if (config.zone.id.empty()) { + config.zone.id = "default"; + } + if (config.zone.name.empty()) { + config.zone.name = "default"; + } + + // add default placement if it doesn't exist + rgw_pool pool; + RGWZonePlacementInfo placement; + placement.storage_classes.set_storage_class( + RGW_STORAGE_CLASS_STANDARD, &pool, nullptr); + config.zone.placement_pools.emplace("default-placement", + std::move(placement)); + + std::set pools; + int r = rgw::init_zone_pool_names(dpp, null_yield, pools, config.zone); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to set default zone pool names" << dendl; + throw std::system_error(-r, std::system_category()); + } + + // verify that config.zonegroup only contains config.zone + if (config.zonegroup.zones.size() > 1) { + ldpp_dout(dpp, 0) << "zonegroup cannot contain multiple zones" << dendl; + throw std::system_error(make_error_code(std::errc::invalid_argument)); + } + + if (config.zonegroup.zones.size() == 1) { + auto z = config.zonegroup.zones.begin(); + if (z->first != config.zone.id) { + ldpp_dout(dpp, 0) << "zonegroup contains unknown zone id=" + << z->first << dendl; + throw std::system_error(make_error_code(std::errc::invalid_argument)); + } + if (z->second.id != config.zone.id) { + ldpp_dout(dpp, 0) << "zonegroup contains unknown zone id=" + << z->second.id << dendl; + throw std::system_error(make_error_code(std::errc::invalid_argument)); + } + if (z->second.name != config.zone.name) { + ldpp_dout(dpp, 0) << "zonegroup contains unknown zone name=" + << z->second.name << dendl; + throw std::system_error(make_error_code(std::errc::invalid_argument)); + } + if (config.zonegroup.master_zone != config.zone.id) { + ldpp_dout(dpp, 0) << "zonegroup contains unknown master_zone=" + << config.zonegroup.master_zone << dendl; + throw std::system_error(make_error_code(std::errc::invalid_argument)); + } + } else { + // add the zone to the group + const bool is_master = true; + const bool read_only = false; + std::list endpoints; + std::list sync_from; + std::list sync_from_rm; + rgw::zone_features::set enable_features; + rgw::zone_features::set disable_features; + + enable_features.insert(rgw::zone_features::supported.begin(), + rgw::zone_features::supported.end()); + + int r = rgw::add_zone_to_group(dpp, config.zonegroup, config.zone, + &is_master, &read_only, endpoints, + nullptr, nullptr, sync_from, sync_from_rm, + nullptr, std::nullopt, + enable_features, disable_features); + if (r < 0) { + ldpp_dout(dpp, 0) << "failed to add zone to zonegroup: " + << cpp_strerror(r) << dendl; + throw std::system_error(-r, std::system_category()); + } + + config.zonegroup.enabled_features.insert(rgw::zone_features::enabled.begin(), + rgw::zone_features::enabled.end()); + } + + // insert the default placement target if it doesn't exist + auto target = RGWZoneGroupPlacementTarget{.name = "default-placement"}; + config.zonegroup.placement_targets.emplace(target.name, target); + if (config.zonegroup.default_placement.name.empty()) { + config.zonegroup.default_placement.name = target.name; + } +} + +} // anonymous namespace + +auto create_json_config_store(const DoutPrefixProvider* dpp, + const std::string& filename) + -> std::unique_ptr +{ + DecodedConfig config; + parse_config(dpp, filename.c_str()); + sanity_check_config(dpp, config); + return create_immutable_config_store(dpp, config.zonegroup, config.zone, + config.period_config); +} + +} // namespace rgw::sal -- cgit v1.2.3