Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / common / options.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #pragma once
5
6 #include <string>
7 #include <list>
8 #include <boost/variant.hpp>
9 #include "include/str_list.h"
10 #include "msg/msg_types.h"
11 #include "include/uuid.h"
12
13 struct Option {
14   enum type_t {
15     TYPE_UINT,
16     TYPE_INT,
17     TYPE_STR,
18     TYPE_FLOAT,
19     TYPE_BOOL,
20     TYPE_ADDR,
21     TYPE_UUID,
22   };
23
24   const char *type_to_str(type_t t) const {
25     switch (t) {
26     case TYPE_UINT: return "uint64_t";
27     case TYPE_INT: return "int64_t";
28     case TYPE_STR: return "std::string";
29     case TYPE_FLOAT: return "double";
30     case TYPE_BOOL: return "bool";
31     case TYPE_ADDR: return "entity_addr_t";
32     case TYPE_UUID: return "uuid_d";
33     default: return "unknown";
34     }
35   }
36
37   /**
38    * Basic: for users, configures some externally visible functional aspect
39    * Advanced: for users, configures some internal behaviour
40    * Development: not for users.  May be dangerous, may not be documented.
41    */
42   enum level_t {
43     LEVEL_BASIC,
44     LEVEL_ADVANCED,
45     LEVEL_DEV,
46   };
47
48   const char *level_to_str(level_t l) const {
49     switch(l) {
50       case LEVEL_BASIC: return "basic";
51       case LEVEL_ADVANCED: return "advanced";
52       case LEVEL_DEV: return "developer";
53       default: return "unknown";
54     }
55   }
56
57   using value_t = boost::variant<
58     boost::blank,
59     std::string,
60     uint64_t,
61     int64_t,
62     double,
63     bool,
64     entity_addr_t,
65     uuid_d>;
66   const std::string name;
67   const type_t type;
68   const level_t level;
69
70   std::string desc;
71   std::string long_desc;
72
73   value_t value;
74   value_t daemon_value;
75
76   // Items like mon, osd, rgw, rbd, ceph-fuse.  This is advisory metadata
77   // for presentation layers (like web dashboards, or generated docs), so that
78   // they know which options to display where.
79   // Additionally: "common" for settings that exist in any Ceph code.  Do
80   // not use common for settings that are just shared some places: for those
81   // places, list them.
82   std::list<const char*> services;
83
84   // Topics like:
85   // "service": a catchall for the boring stuff like log/asok paths.
86   // "network"
87   // "performance": a setting that may need adjustment depending on
88   //                environment/workload to get best performance.
89   std::list<const char*> tags;
90
91   std::list<const char*> see_also;
92
93   value_t min, max;
94   std::list<std::string> enum_allowed;
95
96   bool safe;
97
98   /**
99    * Return nonzero and set second argument to error string if the
100    * value is invalid.
101    *
102    * These callbacks are more than just validators, as they can also
103    * modify the value as it passes through.
104    */
105   typedef std::function<int(std::string *, std::string *)> validator_fn_t;
106   validator_fn_t validator;
107
108   Option(std::string const &name, type_t t, level_t l)
109     : name(name), type(t), level(l), safe(false)
110   {
111     // While value_t is nullable (via boost::blank), we don't ever
112     // want it set that way in an Option instance: within an instance,
113     // the type of ::value should always match the declared type.
114     if (type == TYPE_INT) {
115       value = int64_t(0);
116     } else if (type == TYPE_UINT) {
117       value = uint64_t(0);
118     } else if (type == TYPE_STR) {
119       value = std::string("");
120     } else if (type == TYPE_FLOAT) {
121       value = 0.0;
122     } else if (type == TYPE_BOOL) {
123       value = false;
124     } else if (type == TYPE_ADDR) {
125       value = entity_addr_t();
126     } else if (type == TYPE_UUID) {
127       value = uuid_d();
128     } else {
129       ceph_abort();
130     }
131   }
132
133   void dump_value(const char *field_name, const value_t &v, Formatter *f) const;
134
135   // Validate and potentially modify incoming string value
136   int pre_validate(std::string *new_value, std::string *err) const;
137
138   // Validate properly typed value against bounds
139   int validate(const Option::value_t &new_value, std::string *err) const;
140
141   // const char * must be explicit to avoid it being treated as an int
142   Option& set_value(value_t& v, const char *new_value) {
143     v = std::string(new_value);
144     return *this;
145   }
146
147   // bool is an integer, but we don't think so. teach it the hard way.
148   template<typename T>
149   using is_not_integer = std::enable_if<!std::is_integral<T>::value ||
150                                         std::is_same<T, bool>::value, int>;
151   template<typename T>
152   using is_integer = std::enable_if<std::is_integral<T>::value &&
153                                     !std::is_same<T, bool>::value, int>;
154   template<typename T, typename is_not_integer<T>::type = 0>
155   Option& set_value(value_t& v, const T& new_value) {
156     v = new_value;
157     return *this;
158   }
159
160   // For potentially ambiguous types, inspect Option::type and
161   // do some casting.  This is necessary to make sure that setting
162   // a float option to "0" actually sets the double part of variant.
163   template<typename T, typename is_integer<T>::type = 0>
164   Option& set_value(value_t& v, T new_value) {
165     if (type == TYPE_INT) {
166       v = int64_t(new_value);
167     } else if (type == TYPE_UINT) {
168       v = uint64_t(new_value);
169     } else if (type == TYPE_FLOAT) {
170       v = double(new_value);
171     } else if (type == TYPE_BOOL) {
172       v = bool(new_value);
173     } else {
174       std::cerr << "Bad type in set_value: " << name << ": "
175                 << typeid(T).name() << std::endl;
176       ceph_abort();
177     }
178     return *this;
179   }
180
181   template<typename T>
182   Option& set_default(const T& v) {
183     return set_value(value, v);
184   }
185
186   template<typename T>
187   Option& set_daemon_default(const T& v) {
188     return set_value(daemon_value, v);
189   }
190   Option& add_tag(const char* tag) {
191     tags.push_back(tag);
192     return *this;
193   }
194   Option& add_tag(std::initializer_list<const char*> ts) {
195     tags.insert(tags.end(), ts);
196     return *this;
197   }
198   Option& add_service(const char* service) {
199     services.push_back(service);
200     return *this;
201   }
202   Option& add_service(std::initializer_list<const char*> ss) {
203     services.insert(services.end(), ss);
204     return *this;
205   }
206   Option& add_see_also(const char* t) {
207     see_also.push_back(t);
208     return *this;
209   }
210   Option& add_see_also(std::initializer_list<const char*> ts) {
211     see_also.insert(see_also.end(), ts);
212     return *this;
213   }
214   Option& set_description(const char* new_desc) {
215     desc = new_desc;
216     return *this;
217   }
218   Option& set_long_description(const char* new_desc) {
219     long_desc = new_desc;
220     return *this;
221   }
222
223   template<typename T>
224   Option& set_min(const T& mi) {
225     set_value(min, mi);
226     return *this;
227   }
228
229   template<typename T>
230   Option& set_min_max(const T& mi, const T& ma) {
231     set_value(min, mi);
232     set_value(max, ma);
233     return *this;
234   }
235
236   Option& set_enum_allowed(const std::list<std::string> allowed)
237   {
238     enum_allowed = allowed;
239     return *this;
240   }
241
242   Option &set_safe() {
243     safe = true;
244     return *this;
245   }
246
247   Option &set_validator(const validator_fn_t  &validator_)
248   {
249     validator = validator_;
250     return *this;
251   }
252
253   void dump(Formatter *f) const;
254
255   /**
256    * A crude indicator of whether the value may be
257    * modified safely at runtime -- should be replaced
258    * with proper locking!
259    */
260   bool is_safe() const
261   {
262     return safe || type == TYPE_BOOL || type == TYPE_INT
263                 || type == TYPE_UINT || type == TYPE_FLOAT;
264   }
265 };
266
267 extern const std::vector<Option> ceph_options;
268