1 // vim: ts=8 sw=2 smarttab ft=cpp
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2022 Red Hat, Inc.
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include <system_error>
16 #include "include/buffer.h"
17 #include "common/errno.h"
18 #include "common/ceph_json.h"
20 #include "driver/immutable_config/store.h"
27 struct DecodedConfig
{
28 RGWZoneGroup zonegroup
;
30 RGWPeriodConfig period_config
;
32 void decode_json(JSONObj
*obj
)
34 JSONDecoder::decode_json("zonegroup", zonegroup
, obj
);
35 JSONDecoder::decode_json("zone", zone
, obj
);
36 JSONDecoder::decode_json("period_config", period_config
, obj
);
40 static void parse_config(const DoutPrefixProvider
* dpp
, const char* filename
)
44 int r
= bl
.read_file(filename
, &errmsg
);
46 ldpp_dout(dpp
, 0) << "failed to read json config file '" << filename
47 << "': " << errmsg
<< dendl
;
48 throw std::system_error(-r
, std::system_category());
52 if (!p
.parse(bl
.c_str(), bl
.length())) {
53 ldpp_dout(dpp
, 0) << "failed to parse json config file" << dendl
;
54 throw std::system_error(make_error_code(std::errc::invalid_argument
));
59 decode_json_obj(config
, &p
);
60 } catch (const JSONDecoder::err
& e
) {
61 ldpp_dout(dpp
, 0) << "failed to decode JSON input: " << e
.what() << dendl
;
62 throw std::system_error(make_error_code(std::errc::invalid_argument
));
66 void sanity_check_config(const DoutPrefixProvider
* dpp
, DecodedConfig
& config
)
68 if (config
.zonegroup
.id
.empty()) {
69 config
.zonegroup
.id
= "default";
71 if (config
.zonegroup
.name
.empty()) {
72 config
.zonegroup
.name
= "default";
74 if (config
.zonegroup
.api_name
.empty()) {
75 config
.zonegroup
.api_name
= config
.zonegroup
.name
;
78 if (config
.zone
.id
.empty()) {
79 config
.zone
.id
= "default";
81 if (config
.zone
.name
.empty()) {
82 config
.zone
.name
= "default";
85 // add default placement if it doesn't exist
87 RGWZonePlacementInfo placement
;
88 placement
.storage_classes
.set_storage_class(
89 RGW_STORAGE_CLASS_STANDARD
, &pool
, nullptr);
90 config
.zone
.placement_pools
.emplace("default-placement",
91 std::move(placement
));
93 std::set
<rgw_pool
> pools
;
94 int r
= rgw::init_zone_pool_names(dpp
, null_yield
, pools
, config
.zone
);
96 ldpp_dout(dpp
, 0) << "failed to set default zone pool names" << dendl
;
97 throw std::system_error(-r
, std::system_category());
100 // verify that config.zonegroup only contains config.zone
101 if (config
.zonegroup
.zones
.size() > 1) {
102 ldpp_dout(dpp
, 0) << "zonegroup cannot contain multiple zones" << dendl
;
103 throw std::system_error(make_error_code(std::errc::invalid_argument
));
106 if (config
.zonegroup
.zones
.size() == 1) {
107 auto z
= config
.zonegroup
.zones
.begin();
108 if (z
->first
!= config
.zone
.id
) {
109 ldpp_dout(dpp
, 0) << "zonegroup contains unknown zone id="
110 << z
->first
<< dendl
;
111 throw std::system_error(make_error_code(std::errc::invalid_argument
));
113 if (z
->second
.id
!= config
.zone
.id
) {
114 ldpp_dout(dpp
, 0) << "zonegroup contains unknown zone id="
115 << z
->second
.id
<< dendl
;
116 throw std::system_error(make_error_code(std::errc::invalid_argument
));
118 if (z
->second
.name
!= config
.zone
.name
) {
119 ldpp_dout(dpp
, 0) << "zonegroup contains unknown zone name="
120 << z
->second
.name
<< dendl
;
121 throw std::system_error(make_error_code(std::errc::invalid_argument
));
123 if (config
.zonegroup
.master_zone
!= config
.zone
.id
) {
124 ldpp_dout(dpp
, 0) << "zonegroup contains unknown master_zone="
125 << config
.zonegroup
.master_zone
<< dendl
;
126 throw std::system_error(make_error_code(std::errc::invalid_argument
));
129 // add the zone to the group
130 const bool is_master
= true;
131 const bool read_only
= false;
132 std::list
<std::string
> endpoints
;
133 std::list
<std::string
> sync_from
;
134 std::list
<std::string
> sync_from_rm
;
135 rgw::zone_features::set enable_features
;
136 rgw::zone_features::set disable_features
;
138 enable_features
.insert(rgw::zone_features::supported
.begin(),
139 rgw::zone_features::supported
.end());
141 int r
= rgw::add_zone_to_group(dpp
, config
.zonegroup
, config
.zone
,
142 &is_master
, &read_only
, endpoints
,
143 nullptr, nullptr, sync_from
, sync_from_rm
,
144 nullptr, std::nullopt
,
145 enable_features
, disable_features
);
147 ldpp_dout(dpp
, 0) << "failed to add zone to zonegroup: "
148 << cpp_strerror(r
) << dendl
;
149 throw std::system_error(-r
, std::system_category());
152 config
.zonegroup
.enabled_features
= std::move(enable_features
);
155 // insert the default placement target if it doesn't exist
156 auto target
= RGWZoneGroupPlacementTarget
{.name
= "default-placement"};
157 config
.zonegroup
.placement_targets
.emplace(target
.name
, target
);
158 if (config
.zonegroup
.default_placement
.name
.empty()) {
159 config
.zonegroup
.default_placement
.name
= target
.name
;
163 } // anonymous namespace
165 auto create_json_config_store(const DoutPrefixProvider
* dpp
,
166 const std::string
& filename
)
167 -> std::unique_ptr
<ConfigStore
>
169 DecodedConfig config
;
170 parse_config(dpp
, filename
.c_str());
171 sanity_check_config(dpp
, config
);
172 return create_immutable_config_store(dpp
, config
.zonegroup
, config
.zone
,
173 config
.period_config
);
176 } // namespace rgw::sal