]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/MgrStatMonitor.cc
df92265d30797404c02534e89d51826704a4ed04
[ceph.git] / ceph / src / mon / MgrStatMonitor.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "MgrStatMonitor.h"
5 #include "mon/OSDMonitor.h"
6 #include "mon/PGMap.h"
7 #include "mon/PGMonitor.h"
8 #include "messages/MGetPoolStats.h"
9 #include "messages/MGetPoolStatsReply.h"
10 #include "messages/MMonMgrReport.h"
11 #include "messages/MStatfs.h"
12 #include "messages/MStatfsReply.h"
13
14 class MgrPGStatService : public MonPGStatService {
15 PGMapDigest& digest;
16 public:
17 MgrPGStatService(PGMapDigest& d) : digest(d) {}
18
19 const pool_stat_t* get_pool_stat(int poolid) const override {
20 auto i = digest.pg_pool_sum.find(poolid);
21 if (i != digest.pg_pool_sum.end()) {
22 return &i->second;
23 }
24 return nullptr;
25 }
26
27 ceph_statfs get_statfs() const override {
28 return digest.get_statfs();
29 }
30
31 void print_summary(Formatter *f, ostream *out) const override {
32 digest.print_summary(f, out);
33 }
34 void dump_info(Formatter *f) const override {
35 digest.dump(f);
36 }
37 void dump_fs_stats(stringstream *ss,
38 Formatter *f,
39 bool verbose) const override {
40 digest.dump_fs_stats(ss, f, verbose);
41 }
42 void dump_pool_stats(const OSDMap& osdm, stringstream *ss, Formatter *f,
43 bool verbose) const override {
44 digest.dump_pool_stats_full(osdm, ss, f, verbose);
45 }
46 };
47
48
49 #define dout_subsys ceph_subsys_mon
50 #undef dout_prefix
51 #define dout_prefix _prefix(_dout, mon)
52 static ostream& _prefix(std::ostream *_dout, Monitor *mon) {
53 return *_dout << "mon." << mon->name << "@" << mon->rank
54 << "(" << mon->get_state_name()
55 << ").mgrstat ";
56 }
57
58 MgrStatMonitor::MgrStatMonitor(Monitor *mn, Paxos *p, const string& service_name)
59 : PaxosService(mn, p, service_name),
60 pgservice(new MgrPGStatService(digest))
61 {
62 }
63
64 MgrStatMonitor::~MgrStatMonitor() = default;
65
66 MonPGStatService *MgrStatMonitor::get_pg_stat_service()
67 {
68 return pgservice.get();
69 }
70
71 void MgrStatMonitor::create_initial()
72 {
73 dout(10) << dendl;
74 version = 0;
75 }
76
77 void MgrStatMonitor::update_from_paxos(bool *need_bootstrap)
78 {
79 version = get_last_committed();
80 dout(10) << " " << version << dendl;
81 bufferlist bl;
82 get_version(version, bl);
83 if (version) {
84 assert(bl.length());
85 auto p = bl.begin();
86 ::decode(digest, p);
87 ::decode(health_summary, p);
88 ::decode(health_detail, p);
89 }
90 }
91
92 void MgrStatMonitor::create_pending()
93 {
94 dout(10) << " " << version << dendl;
95 pending_digest = digest;
96 pending_health_summary = health_summary;
97 pending_health_detail = health_detail;
98 }
99
100 void MgrStatMonitor::encode_pending(MonitorDBStore::TransactionRef t)
101 {
102 ++version;
103 if (version < mon->pgmon()->get_last_committed()) {
104 // fast-forward to pgmon version to ensure clients don't see a
105 // jump back in time for MGetPoolStats and MStatFs.
106 version = mon->pgmon()->get_last_committed() + 1;
107 }
108 dout(10) << " " << version << dendl;
109 bufferlist bl;
110 ::encode(pending_digest, bl, mon->get_quorum_con_features());
111 ::encode(pending_health_summary, bl);
112 ::encode(pending_health_detail, bl);
113 put_version(t, version, bl);
114 put_last_committed(t, version);
115 }
116
117 version_t MgrStatMonitor::get_trim_to()
118 {
119 // we don't actually need *any* old states, but keep a few.
120 if (version > 5) {
121 return version - 5;
122 }
123 return 0;
124 }
125
126 void MgrStatMonitor::on_active()
127 {
128 }
129
130 void MgrStatMonitor::get_health(list<pair<health_status_t,string> >& summary,
131 list<pair<health_status_t,string> > *detail,
132 CephContext *cct) const
133 {
134 summary.insert(summary.end(), health_summary.begin(), health_summary.end());
135 if (detail) {
136 detail->insert(detail->end(), health_detail.begin(), health_detail.end());
137 }
138 }
139
140 void MgrStatMonitor::tick()
141 {
142 }
143
144 void MgrStatMonitor::print_summary(Formatter *f, std::ostream *ss) const
145 {
146 pgservice->print_summary(f, ss);
147 }
148
149 bool MgrStatMonitor::preprocess_query(MonOpRequestRef op)
150 {
151 auto m = static_cast<PaxosServiceMessage*>(op->get_req());
152 switch (m->get_type()) {
153 case CEPH_MSG_STATFS:
154 return preprocess_statfs(op);
155 case MSG_MON_MGR_REPORT:
156 return preprocess_report(op);
157 case MSG_GETPOOLSTATS:
158 return preprocess_getpoolstats(op);
159 default:
160 mon->no_reply(op);
161 derr << "Unhandled message type " << m->get_type() << dendl;
162 return true;
163 }
164 }
165
166 bool MgrStatMonitor::prepare_update(MonOpRequestRef op)
167 {
168 auto m = static_cast<PaxosServiceMessage*>(op->get_req());
169 switch (m->get_type()) {
170 case MSG_MON_MGR_REPORT:
171 return prepare_report(op);
172 default:
173 mon->no_reply(op);
174 derr << "Unhandled message type " << m->get_type() << dendl;
175 return true;
176 }
177 }
178
179 bool MgrStatMonitor::preprocess_report(MonOpRequestRef op)
180 {
181 return false;
182 }
183
184 bool MgrStatMonitor::prepare_report(MonOpRequestRef op)
185 {
186 auto m = static_cast<MMonMgrReport*>(op->get_req());
187 bufferlist bl = m->get_data();
188 auto p = bl.begin();
189 ::decode(pending_digest, p);
190 dout(10) << __func__ << " " << pending_digest << dendl;
191 pending_health_summary.swap(m->health_summary);
192 pending_health_detail.swap(m->health_detail);
193 return true;
194 }
195
196 bool MgrStatMonitor::preprocess_getpoolstats(MonOpRequestRef op)
197 {
198 op->mark_pgmon_event(__func__);
199 auto m = static_cast<MGetPoolStats*>(op->get_req());
200 auto session = m->get_session();
201 if (!session)
202 return true;
203 if (!session->is_capable("pg", MON_CAP_R)) {
204 dout(0) << "MGetPoolStats received from entity with insufficient caps "
205 << session->caps << dendl;
206 return true;
207 }
208 if (m->fsid != mon->monmap->fsid) {
209 dout(0) << __func__ << " on fsid "
210 << m->fsid << " != " << mon->monmap->fsid << dendl;
211 return true;
212 }
213 epoch_t ver = 0;
214 if (mon->pgservice == get_pg_stat_service()) {
215 ver = get_last_committed();
216 } else {
217 ver = mon->pgmon()->get_last_committed();
218 }
219 auto reply = new MGetPoolStatsReply(m->fsid, m->get_tid(), ver);
220 for (const auto& pool_name : m->pools) {
221 const auto pool_id = mon->osdmon()->osdmap.lookup_pg_pool_name(pool_name);
222 if (pool_id == -ENOENT)
223 continue;
224 auto pool_stat = mon->pgservice->get_pool_stat(pool_id);
225 if (!pool_stat)
226 continue;
227 reply->pool_stats[pool_name] = *pool_stat;
228 }
229 mon->send_reply(op, reply);
230 return true;
231 }
232
233 bool MgrStatMonitor::preprocess_statfs(MonOpRequestRef op)
234 {
235 op->mark_pgmon_event(__func__);
236 auto statfs = static_cast<MStatfs*>(op->get_req());
237 auto session = statfs->get_session();
238 if (!session)
239 return true;
240 if (!session->is_capable("pg", MON_CAP_R)) {
241 dout(0) << "MStatfs received from entity with insufficient privileges "
242 << session->caps << dendl;
243 return true;
244 }
245 if (statfs->fsid != mon->monmap->fsid) {
246 dout(0) << __func__ << " on fsid " << statfs->fsid
247 << " != " << mon->monmap->fsid << dendl;
248 return true;
249 }
250 dout(10) << __func__ << " " << *statfs
251 << " from " << statfs->get_orig_source() << dendl;
252 epoch_t ver = 0;
253 if (mon->pgservice == get_pg_stat_service()) {
254 ver = get_last_committed();
255 } else {
256 ver = mon->pgmon()->get_last_committed();
257 }
258 auto reply = new MStatfsReply(statfs->fsid, statfs->get_tid(), ver);
259 reply->h.st = mon->pgservice->get_statfs();
260 mon->send_reply(op, reply);
261 return true;
262 }