]>
git.proxmox.com Git - ceph.git/blob - ceph/src/common/options.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
6 #include "common/Formatter.h"
7 #include "common/options/build_options.h"
9 // Helpers for validators
10 #include "include/stringify.h"
11 #include "include/common_fwd.h"
12 #include <boost/algorithm/string.hpp>
13 #include <boost/lexical_cast.hpp>
16 // Definitions for enums
17 #include "common/perf_counters.h"
19 // rbd feature and io operation validation
20 #include "librbd/Features.h"
21 #include "librbd/io/IoOperations.h"
24 using std::ostringstream
;
26 using ceph::Formatter
;
27 using ceph::parse_timespan
;
33 explicit printer(ostream
& os
)
36 void operator()(const T
& v
) const {
39 void operator()(std::monostate
) const {
42 void operator()(bool v
) const {
43 out
<< (v
? "true" : "false");
45 void operator()(double v
) const {
46 out
<< std::fixed
<< v
<< std::defaultfloat
;
48 void operator()(const Option::size_t& v
) const {
51 void operator()(const std::chrono::seconds v
) const {
54 void operator()(const std::chrono::milliseconds v
) const {
60 ostream
& operator<<(ostream
& os
, const Option::value_t
& v
) {
66 void Option::dump_value(const char *field_name
,
67 const Option::value_t
&v
, Formatter
*f
) const
70 // This should be nil but Formatter doesn't allow it.
71 f
->dump_string(field_name
, "");
76 f
->dump_int(field_name
, std::get
<int64_t>(v
)); break;
78 f
->dump_unsigned(field_name
, std::get
<uint64_t>(v
)); break;
80 f
->dump_string(field_name
, std::get
<std::string
>(v
)); break;
82 f
->dump_float(field_name
, std::get
<double>(v
)); break;
84 f
->dump_bool(field_name
, std::get
<bool>(v
)); break;
86 f
->dump_stream(field_name
) << v
; break;
90 int Option::pre_validate(std::string
*new_value
, std::string
*err
) const
93 return validator(new_value
, err
);
99 int Option::validate(const Option::value_t
&new_value
, std::string
*err
) const
101 // Generic validation: min
102 if (min
!= value_t
{}) {
103 if (new_value
< min
) {
104 std::ostringstream oss
;
105 oss
<< "Value '" << new_value
<< "' is below minimum " << min
;
111 // Generic validation: max
112 if (max
!= value_t
{}) {
113 if (new_value
> max
) {
114 std::ostringstream oss
;
115 oss
<< "Value '" << new_value
<< "' exceeds maximum " << max
;
121 // Generic validation: enum
122 if (!enum_allowed
.empty() && type
== Option::TYPE_STR
) {
123 auto found
= std::find(enum_allowed
.begin(), enum_allowed
.end(),
124 std::get
<std::string
>(new_value
));
125 if (found
== enum_allowed
.end()) {
126 std::ostringstream oss
;
127 oss
<< "'" << new_value
<< "' is not one of the permitted "
128 "values: " << joinify(enum_allowed
.begin(),
139 int Option::parse_value(
140 const std::string
& raw_val
,
142 std::string
*error_message
,
143 std::string
*normalized_value
) const
145 std::string val
= raw_val
;
147 int r
= pre_validate(&val
, error_message
);
152 if (type
== Option::TYPE_INT
) {
153 int64_t f
= strict_si_cast
<int64_t>(val
, error_message
);
154 if (!error_message
->empty()) {
158 } else if (type
== Option::TYPE_UINT
) {
159 uint64_t f
= strict_si_cast
<uint64_t>(val
, error_message
);
160 if (!error_message
->empty()) {
164 } else if (type
== Option::TYPE_STR
) {
166 } else if (type
== Option::TYPE_FLOAT
) {
167 double f
= strict_strtod(val
.c_str(), error_message
);
168 if (!error_message
->empty()) {
173 } else if (type
== Option::TYPE_BOOL
) {
174 bool b
= strict_strtob(val
.c_str(), error_message
);
175 if (!error_message
->empty()) {
180 } else if (type
== Option::TYPE_ADDR
) {
182 if (!addr
.parse(val
)){
186 } else if (type
== Option::TYPE_ADDRVEC
) {
187 entity_addrvec_t addr
;
188 if (!addr
.parse(val
.c_str())){
192 } else if (type
== Option::TYPE_UUID
) {
194 if (!uuid
.parse(val
.c_str())) {
198 } else if (type
== Option::TYPE_SIZE
) {
199 Option::size_t sz
{strict_iecstrtoll(val
, error_message
)};
200 if (!error_message
->empty()) {
204 } else if (type
== Option::TYPE_SECS
) {
206 *out
= parse_timespan(val
);
207 } catch (const std::invalid_argument
& e
) {
208 *error_message
= e
.what();
211 } else if (type
== Option::TYPE_MILLISECS
) {
213 *out
= std::chrono::milliseconds(std::stoull(val
));
214 } catch (const std::logic_error
& e
) {
215 *error_message
= e
.what();
222 r
= validate(*out
, error_message
);
227 if (normalized_value
) {
228 *normalized_value
= to_str(*out
);
233 void Option::dump(Formatter
*f
) const
235 f
->dump_string("name", name
);
237 f
->dump_string("type", type_to_str(type
));
239 f
->dump_string("level", level_to_str(level
));
241 f
->dump_string("desc", desc
);
242 f
->dump_string("long_desc", long_desc
);
244 dump_value("default", value
, f
);
245 dump_value("daemon_default", daemon_value
, f
);
247 f
->open_array_section("tags");
248 for (const auto t
: tags
) {
249 f
->dump_string("tag", t
);
253 f
->open_array_section("services");
254 for (const auto s
: services
) {
255 f
->dump_string("service", s
);
259 f
->open_array_section("see_also");
260 for (const auto sa
: see_also
) {
261 f
->dump_string("see_also", sa
);
265 if (type
== TYPE_STR
) {
266 f
->open_array_section("enum_values");
267 for (const auto &ea
: enum_allowed
) {
268 f
->dump_string("enum_value", ea
);
273 dump_value("min", min
, f
);
274 dump_value("max", max
, f
);
276 f
->dump_bool("can_update_at_runtime", can_update_at_runtime());
278 f
->open_array_section("flags");
279 if (has_flag(FLAG_RUNTIME
)) {
280 f
->dump_string("option", "runtime");
282 if (has_flag(FLAG_NO_MON_UPDATE
)) {
283 f
->dump_string("option", "no_mon_update");
285 if (has_flag(FLAG_STARTUP
)) {
286 f
->dump_string("option", "startup");
288 if (has_flag(FLAG_CLUSTER_CREATE
)) {
289 f
->dump_string("option", "cluster_create");
291 if (has_flag(FLAG_CREATE
)) {
292 f
->dump_string("option", "create");
297 std::string
Option::to_str(const Option::value_t
& v
)
302 void Option::print(ostream
*out
) const
304 *out
<< name
<< " - " << desc
<< "\n";
305 *out
<< " (" << type_to_str(type
) << ", " << level_to_str(level
) << ")\n";
306 if (daemon_value
!= value_t
{}) {
307 *out
<< " Default (non-daemon): " << stringify(value
) << "\n";
308 *out
<< " Default (daemon): " << stringify(daemon_value
) << "\n";
310 *out
<< " Default: " << stringify(value
) << "\n";
312 if (!enum_allowed
.empty()) {
313 *out
<< " Possible values: ";
314 for (auto& i
: enum_allowed
) {
315 *out
<< " " << stringify(i
);
319 if (min
!= value_t
{}) {
320 *out
<< " Minimum: " << stringify(min
) << "\n"
321 << " Maximum: " << stringify(max
) << "\n";
323 *out
<< " Can update at runtime: "
324 << (can_update_at_runtime() ? "true" : "false") << "\n";
325 if (!services
.empty()) {
326 *out
<< " Services: " << services
<< "\n";
329 *out
<< " Tags: " << tags
<< "\n";
331 if (!see_also
.empty()) {
332 *out
<< " See also: " << see_also
<< "\n";
335 if (long_desc
.size()) {
336 *out
<< "\n" << long_desc
<< "\n";
340 const std::vector
<Option
> ceph_options
= build_options();