1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
20 #include <boost/container/small_vector.hpp>
21 #include "common/ConfUtils.h"
22 #include "common/code_environment.h"
23 #include "log/SubsystemMap.h"
24 #include "common/options.h"
25 #include "common/subsys_types.h"
26 #include "common/config_tracker.h"
27 #include "common/config_values.h"
28 #include "include/common_fwd.h"
40 extern const char *ceph_conf_level_name(int level
);
42 /** This class represents the current Ceph configuration.
44 * For Ceph daemons, this is the daemon configuration. Log levels, caching
45 * settings, btrfs settings, and so forth can all be found here. For libcephfs
46 * and librados users, this is the configuration associated with their context.
48 * For information about how this class is loaded from a configuration file,
49 * see common/ConfUtils.
53 * There are 3 ways to read the ceph context-- the old way and two new ways.
54 * In the old way, code would simply read the public variables of the
55 * configuration, without taking a lock. In the new way #1, code registers a
56 * configuration observer which receives callbacks when a value changes. These
57 * callbacks take place under the md_config_t lock. Alternatively one can use
58 * get_val(const char *name) method to safely get a copy of the value.
60 * To prevent serious problems resulting from thread-safety issues, we disallow
61 * changing std::string configuration values after
62 * md_config_t::safe_to_start_threads becomes true. You can still
63 * change integer or floating point values, and the option declared with
64 * SAFE_OPTION macro. Notice the latter options can not be read directly
65 * (conf->foo), one should use either observers or get_val() method
66 * (conf->get_val("foo")).
68 * FIXME: really we shouldn't allow changing integer or floating point values
69 * while another thread is reading them, either.
73 typedef std::variant
<int64_t ConfigValues::*,
74 uint64_t ConfigValues::*,
75 std::string
ConfigValues::*,
76 double ConfigValues::*,
78 entity_addr_t
ConfigValues::*,
79 entity_addrvec_t
ConfigValues::*,
80 uuid_d
ConfigValues::*> member_ptr_t
;
82 // For use when intercepting configuration updates
83 typedef std::function
<bool(
84 const std::string
&k
, const std::string
&v
)> config_callback
;
86 /// true if we are a daemon (as per CephContext::code_env)
90 * Mapping from legacy config option names to class members
92 std::map
<std::string_view
, member_ptr_t
> legacy_values
;
95 * The configuration schema, in the form of Option objects describing
98 std::map
<std::string_view
, const Option
&> schema
;
100 /// values from mon that we failed to set
101 std::map
<std::string
,std::string
> ignored_mon_values
;
103 /// original raw values saved that may need to re-expand at certain time
104 mutable std::vector
<std::string
> may_reexpand_meta
;
106 /// encoded, cached copy of of values + ignored_mon_values
107 ceph::bufferlist values_bl
;
109 /// version for values_bl; increments each time there is a change
110 uint64_t values_bl_version
= 0;
112 /// encoded copy of defaults (map<string,string>)
113 ceph::bufferlist defaults_bl
;
115 // Create a new md_config_t structure.
116 explicit md_config_t(ConfigValues
& values
,
117 const ConfigTracker
& tracker
,
118 bool is_daemon
=false);
121 // Parse a config file
122 int parse_config_files(ConfigValues
& values
, const ConfigTracker
& tracker
,
123 const char *conf_files
,
124 std::ostream
*warnings
, int flags
);
125 int parse_buffer(ConfigValues
& values
, const ConfigTracker
& tracker
,
126 const char* buf
, size_t len
,
127 std::ostream
*warnings
);
128 void update_legacy_vals(ConfigValues
& values
);
129 // Absorb config settings from the environment
130 void parse_env(unsigned entity_type
,
131 ConfigValues
& values
, const ConfigTracker
& tracker
,
132 const char *env_var
= "CEPH_ARGS");
134 // Absorb config settings from argv
135 int parse_argv(ConfigValues
& values
, const ConfigTracker
& tracker
,
136 std::vector
<const char*>& args
, int level
=CONF_CMDLINE
);
138 // do any commands we got from argv (--show-config, --show-config-val)
139 void do_argv_commands(const ConfigValues
& values
) const;
141 bool _internal_field(const std::string
& k
);
143 void set_safe_to_start_threads();
144 void _clear_safe_to_start_threads(); // this is only used by the unit test
146 /// Look up an option in the schema
147 const Option
*find_option(const std::string_view name
) const;
149 /// Set a default value
150 void set_val_default(ConfigValues
& values
,
151 const ConfigTracker
& tracker
,
152 const std::string_view key
, const std::string
&val
);
154 /// Set a values from mon
155 int set_mon_vals(CephContext
*cct
,
156 ConfigValues
& values
,
157 const ConfigTracker
& tracker
,
158 const std::map
<std::string
,std::string
, std::less
<>>& kv
,
159 config_callback config_cb
);
161 // Called by the Ceph daemons to make configuration changes at runtime
162 int injectargs(ConfigValues
& values
,
163 const ConfigTracker
& tracker
,
164 const std::string
&s
,
167 // Set a configuration value, or crash
168 // Metavariables will be expanded.
169 void set_val_or_die(ConfigValues
& values
, const ConfigTracker
& tracker
,
170 const std::string_view key
, const std::string
&val
);
172 // Set a configuration value.
173 // Metavariables will be expanded.
174 int set_val(ConfigValues
& values
, const ConfigTracker
& tracker
,
175 const std::string_view key
, const char *val
,
176 std::stringstream
*err_ss
=nullptr);
177 int set_val(ConfigValues
& values
, const ConfigTracker
& tracker
,
178 const std::string_view key
, const std::string
& s
,
179 std::stringstream
*err_ss
=nullptr) {
180 return set_val(values
, tracker
, key
, s
.c_str(), err_ss
);
183 /// clear override value
184 int rm_val(ConfigValues
& values
, const std::string_view key
);
186 /// get encoded map<string,map<int32_t,string>> of entire config
187 void get_config_bl(const ConfigValues
& values
,
188 uint64_t have_version
,
189 ceph::buffer::list
*bl
,
190 uint64_t *got_version
);
192 /// get encoded map<string,string> of compiled-in defaults
193 void get_defaults_bl(const ConfigValues
& values
, ceph::buffer::list
*bl
);
195 /// Get the default value of a configuration option
196 std::optional
<std::string
> get_val_default(std::string_view key
);
198 // Get a configuration value.
199 // No metavariables will be returned (they will have already been expanded)
200 int get_val(const ConfigValues
& values
, const std::string_view key
, char **buf
, int len
) const;
201 int get_val(const ConfigValues
& values
, const std::string_view key
, std::string
*val
) const;
202 template<typename T
> const T
get_val(const ConfigValues
& values
, const std::string_view key
) const;
203 template<typename T
, typename Callback
, typename
...Args
>
204 auto with_val(const ConfigValues
& values
, const std::string_view key
,
205 Callback
&& cb
, Args
&&... args
) const ->
206 std::result_of_t
<Callback(const T
&, Args
...)> {
207 return std::forward
<Callback
>(cb
)(
208 std::get
<T
>(this->get_val_generic(values
, key
)),
209 std::forward
<Args
>(args
)...);
212 void get_all_keys(std::vector
<std::string
> *keys
) const;
214 // Return a list of all the sections that the current entity is a member of.
215 std::vector
<std::string
> get_my_sections(const ConfigValues
& values
) const;
217 // Return a list of all sections
218 int get_all_sections(std::vector
<std::string
> §ions
) const;
220 // Get a value from the configuration file that we read earlier.
221 // Metavariables will be expanded if emeta is true.
222 int get_val_from_conf_file(const ConfigValues
& values
,
223 const std::vector
<std::string
> §ions
,
224 const std::string_view key
, std::string
&out
, bool emeta
) const;
226 /// dump all config values to a stream
227 void show_config(const ConfigValues
& values
, std::ostream
& out
) const;
228 /// dump all config values to a formatter
229 void show_config(const ConfigValues
& values
, ceph::Formatter
*f
) const;
231 /// dump all config settings to a formatter
232 void config_options(ceph::Formatter
*f
) const;
234 /// dump config diff from default, conf, mon, etc.
235 void diff(const ConfigValues
& values
,
237 std::string name
= {}) const;
239 /// print/log warnings/errors from parsing the config
240 void complain_about_parse_error(CephContext
*cct
);
243 // we use this to avoid variable expansion loops
244 typedef boost::container::small_vector
<std::pair
<const Option
*,
245 const Option::value_t
*>,
248 void validate_schema();
249 void validate_default_settings();
251 Option::value_t
get_val_generic(const ConfigValues
& values
,
252 const std::string_view key
) const;
253 int _get_val_cstr(const ConfigValues
& values
,
254 const std::string
& key
, char **buf
, int len
) const;
255 Option::value_t
_get_val(const ConfigValues
& values
,
256 const std::string_view key
,
257 expand_stack_t
*stack
=0,
258 std::ostream
*err
=0) const;
259 Option::value_t
_get_val(const ConfigValues
& values
,
261 expand_stack_t
*stack
=0,
262 std::ostream
*err
=0) const;
263 const Option::value_t
& _get_val_default(const Option
& o
) const;
264 Option::value_t
_get_val_nometa(const ConfigValues
& values
,
265 const Option
& o
) const;
267 int _rm_val(ConfigValues
& values
, const std::string_view key
, int level
);
269 void _refresh(ConfigValues
& values
, const Option
& opt
);
271 void _show_config(const ConfigValues
& values
,
272 std::ostream
*out
, ceph::Formatter
*f
) const;
274 int _get_val_from_conf_file(const std::vector
<std::string
> §ions
,
275 const std::string_view key
, std::string
&out
) const;
277 int parse_option(ConfigValues
& values
,
278 const ConfigTracker
& tracker
,
279 std::vector
<const char*>& args
,
280 std::vector
<const char*>::iterator
& i
,
283 int parse_injectargs(ConfigValues
& values
,
284 const ConfigTracker
& tracker
,
285 std::vector
<const char*>& args
,
288 // @returns negative number for an error, otherwise a
289 // @c ConfigValues::set_value_result_t is returned.
291 ConfigValues
& values
,
292 const ConfigTracker
& tracker
,
293 const std::string
&val
,
296 std::string
*error_message
);
298 template <typename T
>
299 void assign_member(member_ptr_t ptr
, const Option::value_t
&val
);
302 void update_legacy_val(ConfigValues
& values
,
304 member_ptr_t member
);
306 Option::value_t
_expand_meta(
307 const ConfigValues
& values
,
308 const Option::value_t
& in
,
310 expand_stack_t
*stack
,
311 std::ostream
*err
) const;
313 public: // for global_init
314 void early_expand_meta(const ConfigValues
& values
,
316 std::ostream
*oss
) const;
318 // for those want to reexpand special meta, e.g, $pid
319 bool finalize_reexpand_meta(ConfigValues
& values
,
320 const ConfigTracker
& tracker
);
322 std::list
<std::string
> get_conffile_paths(const ConfigValues
& values
,
323 const char *conf_files
,
324 std::ostream
*warnings
,
327 const std::string
& get_conf_path() const {
331 static std::string
get_cluster_name(const char* conffile_path
);
332 // The configuration file we read, or NULL if we haven't read one.
334 std::string conf_path
;
336 std::string parse_error
;
339 // This will be set to true when it is safe to start threads.
340 // Once it is true, it will never change.
341 bool safe_to_start_threads
= false;
343 bool do_show_config
= false;
344 std::string do_show_config_value
;
346 std::vector
<Option
> subsys_options
;
349 std::string data_dir_option
; ///< data_dir config option, if any
352 unsigned get_osd_pool_default_min_size(const ConfigValues
& values
,
353 uint8_t size
) const {
354 uint8_t min_size
= get_val
<uint64_t>(values
, "osd_pool_default_min_size");
355 return min_size
? std::min(min_size
, size
) : (size
- size
/ 2);
358 friend class test_md_config_t
;
362 const T
md_config_t::get_val(const ConfigValues
& values
,
363 const std::string_view key
) const {
364 return std::get
<T
>(this->get_val_generic(values
, key
));
367 inline std::ostream
& operator<<(std::ostream
& o
, const std::monostate
&) {
368 return o
<< "INVALID_CONFIG_VALUE";
371 int ceph_resolve_file_search(const std::string
& filename_list
,
372 std::string
& result
);