Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mon / health_check.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 <map>
8
9 #include "include/health.h"
10 #include "common/Formatter.h"
11
12 struct health_check_t {
13   health_status_t severity;
14   std::string summary;
15   std::list<std::string> detail;
16
17   DENC(health_check_t, v, p) {
18     DENC_START(1, 1, p);
19     denc(v.severity, p);
20     denc(v.summary, p);
21     denc(v.detail, p);
22     DENC_FINISH(p);
23   }
24
25   friend bool operator==(const health_check_t& l,
26                          const health_check_t& r) {
27     return l.severity == r.severity &&
28       l.summary == r.summary &&
29       l.detail == r.detail;
30   }
31   friend bool operator!=(const health_check_t& l,
32                          const health_check_t& r) {
33     return !(l == r);
34   }
35
36   void dump(Formatter *f) const {
37     f->dump_stream("severity") << severity;
38
39     f->open_object_section("summary");
40     f->dump_string("message", summary);
41     f->close_section();
42
43     f->open_array_section("detail");
44     for (auto& p : detail) {
45       f->open_object_section("detail_item");
46       f->dump_string("message", p);
47       f->close_section();
48     }
49     f->close_section();
50   }
51
52   static void generate_test_instances(list<health_check_t*>& ls) {
53     ls.push_back(new health_check_t);
54     ls.push_back(new health_check_t);
55     ls.back()->severity = HEALTH_ERR;
56     ls.back()->summary = "summarization";
57     ls.back()->detail = {"one", "two", "three"};
58   }
59 };
60 WRITE_CLASS_DENC(health_check_t)
61
62
63 struct health_check_map_t {
64   map<std::string,health_check_t> checks;
65
66   DENC(health_check_map_t, v, p) {
67     DENC_START(1, 1, p);
68     denc(v.checks, p);
69     DENC_FINISH(p);
70   }
71
72   void dump(Formatter *f) const {
73     for (auto& p : checks) {
74       f->dump_object(p.first.c_str(), p.second);
75     }
76   }
77
78   static void generate_test_instances(list<health_check_map_t*>& ls) {
79     ls.push_back(new health_check_map_t);
80     ls.push_back(new health_check_map_t);
81     {
82       auto& d = ls.back()->add("FOO", HEALTH_WARN, "foo");
83       d.detail.push_back("a");
84       d.detail.push_back("b");
85     }
86     {
87       auto& d = ls.back()->add("BAR", HEALTH_ERR, "bar!");
88       d.detail.push_back("c");
89       d.detail.push_back("d");
90     }
91   }
92
93   void clear() {
94     checks.clear();
95   }
96   bool empty() const {
97     return checks.empty();
98   }
99   void swap(health_check_map_t& other) {
100     checks.swap(other.checks);
101   }
102
103   health_check_t& add(const std::string& code,
104                       health_status_t severity,
105                       const std::string& summary) {
106     assert(checks.count(code) == 0);
107     health_check_t& r = checks[code];
108     r.severity = severity;
109     r.summary = summary;
110     return r;
111   }
112   health_check_t& get_or_add(const std::string& code,
113                              health_status_t severity,
114                              const std::string& summary) {
115     health_check_t& r = checks[code];
116     r.severity = severity;
117     r.summary = summary;
118     return r;
119   }
120
121   void merge(const health_check_map_t& o) {
122     for (auto& p : o.checks) {
123       auto q = checks.find(p.first);
124       if (q == checks.end()) {
125         // new check
126         checks[p.first] = p.second;
127       } else {
128         // merge details, and hope the summary matches!
129         q->second.detail.insert(
130           q->second.detail.end(),
131           p.second.detail.begin(),
132           p.second.detail.end());
133       }
134     }
135   }
136
137   health_status_t dump_summary(Formatter *f, std::string *plain,
138                                const char *sep, bool detail) const {
139     health_status_t r = HEALTH_OK;
140     for (auto& p : checks) {
141       if (r > p.second.severity) {
142         r = p.second.severity;
143       }
144       if (f) {
145         f->open_object_section(p.first.c_str());
146         f->dump_stream("severity") << p.second.severity;
147
148         f->open_object_section("summary");
149         f->dump_string("message", p.second.summary);
150         f->close_section();
151
152         if (detail) {
153           f->open_array_section("detail");
154           for (auto& d : p.second.detail) {
155             f->open_object_section("detail_item");
156             f->dump_string("message", d);
157             f->close_section();
158           }
159           f->close_section();
160         }
161         f->close_section();
162       } else {
163         if (!plain->empty()) {
164           *plain += sep;
165         }
166         *plain += p.second.summary;
167       }
168     }
169     return r;
170   }
171
172   void dump_summary_compat(Formatter *f) const {
173     for (auto& p : checks) {
174       f->open_object_section("item");
175       f->dump_stream("severity") << p.second.severity;
176       f->dump_string("summary", p.second.summary);
177       f->close_section();
178     }
179   }
180
181   void dump_detail(Formatter *f, std::string *plain, bool compat) const {
182     for (auto& p : checks) {
183       if (f) {
184         if (compat) {
185           // this is sloppy, but the best we can do: just dump all of the
186           // individual checks' details together
187           for (auto& d : p.second.detail) {
188             f->dump_string("item", d);
189           }
190         }
191       } else {
192         if (!compat) {
193           *plain += p.first + " " + p.second.summary + "\n";
194         }
195         for (auto& d : p.second.detail) {
196           if (!compat) {
197             *plain += "    ";
198           }
199           *plain += d;
200           *plain += "\n";
201         }
202       }
203     }
204   }
205
206   friend bool operator==(const health_check_map_t& l,
207                          const health_check_map_t& r) {
208     return l.checks == r.checks;
209   }
210   friend bool operator!=(const health_check_map_t& l,
211                          const health_check_map_t& r) {
212     return !(l == r);
213   }
214 };
215 WRITE_CLASS_DENC(health_check_map_t)