summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoao Eduardo Luis <joao.luis@inktank.com>2013-03-01 16:32:24 +0000
committerJoao Eduardo Luis <joao.luis@inktank.com>2013-03-04 11:37:17 +0000
commitde6d0a222b6718306b49b73de4e46e32abe4d6ef (patch)
tree1260c033febb27e77202f5794f29f5b638096cc3
parentcaa0af25192704ee7743097df0c441bd26b9314c (diff)
downloadceph-de6d0a222b6718306b49b73de4e46e32abe4d6ef.tar.gz
mon: Monitor: 'ceph df'
Fixes: #3484 Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
-rw-r--r--src/Makefile.am2
-rw-r--r--src/mon/Monitor.cc25
-rw-r--r--src/mon/PGMonitor.cc154
-rw-r--r--src/mon/PGMonitor.h7
4 files changed, 186 insertions, 2 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 9daf3f22182..441000df963 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,7 +69,7 @@ LIBOS_LDA += -lleveldb -lsnappy
LEVELDB_INCLUDE =
# monitor
-ceph_mon_SOURCES = ceph_mon.cc
+ceph_mon_SOURCES = ceph_mon.cc common/TextTable.cc
ceph_mon_LDFLAGS = $(AM_LDFLAGS)
ceph_mon_LDADD = libmon.a $(LIBOS_LDA) $(LIBGLOBAL_LDA)
ceph_mon_CXXFLAGS = ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS} $(LEVELDB_INCLUDE)
diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc
index 60a022bde25..f719bfe6ba6 100644
--- a/src/mon/Monitor.cc
+++ b/src/mon/Monitor.cc
@@ -2440,7 +2440,8 @@ void Monitor::handle_command(MMonCommand *m)
rs = "must supply options to be parsed in a single string";
r = -EINVAL;
}
- } else if ((m->cmd[0] == "status") || (m->cmd[0] == "health")) {
+ } else if ((m->cmd[0] == "status") || (m->cmd[0] == "health")
+ || (m->cmd[0] == "df")) {
if (!access_r) {
r = -EACCES;
rs = "access denied";
@@ -2493,6 +2494,28 @@ void Monitor::handle_command(MMonCommand *m)
} else {
ss << health_str;
}
+ } else if (string(args[0]) == "df") {
+ if (args.size() > 1) {
+ if (string(args[1]) != "detail") {
+ r = -EINVAL;
+ rs = "usage: df [detail]";
+ goto out;
+ }
+ }
+ bool verbose = (args.size() > 1);
+ if (jf)
+ jf->open_object_section("stats");
+
+ pgmon()->dump_fs_stats(ss, jf, verbose);
+ if (!jf)
+ ss << '\n';
+ pgmon()->dump_pool_stats(ss, jf, verbose);
+
+ if (jf) {
+ jf->close_section();
+ jf->flush(ss);
+ ss << '\n';
+ }
} else {
assert(0 == "We should never get here!");
return;
diff --git a/src/mon/PGMonitor.cc b/src/mon/PGMonitor.cc
index 8245ed6ae6e..cc23bffef25 100644
--- a/src/mon/PGMonitor.cc
+++ b/src/mon/PGMonitor.cc
@@ -34,6 +34,9 @@
#include "common/Formatter.h"
#include "common/ceph_argparse.h"
#include "common/perf_counters.h"
+#include "common/TextTable.h"
+
+#include "include/stringify.h"
#include "osd/osd_types.h"
@@ -894,6 +897,157 @@ bool PGMonitor::check_down_pgs()
return ret;
}
+inline string percentify(const float& a) {
+ stringstream ss;
+ if (a < 0.01)
+ ss << "0";
+ else
+ ss << std::fixed << std::setprecision(2) << a;
+ return ss.str();
+}
+
+//void PGMonitor::dump_object_stat_sum(stringstream& ss, Formatter *f,
+void PGMonitor::dump_object_stat_sum(TextTable &tbl, Formatter *f,
+ object_stat_sum_t &sum, bool verbose)
+{
+ if (f) {
+ f->dump_int("kb_used", SHIFT_ROUND_UP(sum.num_bytes, 10));
+ f->dump_int("bytes_used", sum.num_bytes);
+ f->dump_int("objects", sum.num_objects);
+ if (verbose) {
+ f->dump_int("rd", sum.num_rd);
+ f->dump_int("rd_kb", sum.num_rd_kb);
+ f->dump_int("wr", sum.num_wr);
+ f->dump_int("wr_kb", sum.num_wr_kb);
+ }
+ } else {
+ tbl << stringify(si_t(sum.num_bytes));
+ int64_t kb_used = SHIFT_ROUND_UP(sum.num_bytes, 10);
+ tbl << percentify(((float)kb_used / pg_map.osd_sum.kb)*100);
+ tbl << sum.num_objects;
+ if (verbose) {
+ tbl << stringify(si_t(sum.num_rd))
+ << stringify(si_t(sum.num_wr));
+ }
+ }
+}
+
+void PGMonitor::dump_pool_stats(stringstream &ss, Formatter *f, bool verbose)
+{
+ TextTable tbl;
+
+ if (f) {
+ f->open_array_section("pools");
+ } else {
+ tbl.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("ID", TextTable::LEFT, TextTable::LEFT);
+ if (verbose)
+ tbl.define_column("CATEGORY", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("USED", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("\%USED", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::LEFT);
+ if (verbose) {
+ tbl.define_column("READ", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("WRITE", TextTable::LEFT, TextTable::LEFT);
+ }
+ }
+
+ OSDMap &osdmap = mon->osdmon()->osdmap;
+ for (map<int64_t,pg_pool_t>::const_iterator p = osdmap.get_pools().begin();
+ p != osdmap.get_pools().end(); ++p) {
+ int64_t pool_id = p->first;
+ if ((pool_id < 0) || (pg_map.pg_pool_sum.count(pool_id) == 0))
+ continue;
+ string pool_name = osdmap.get_pool_name(pool_id);
+ pool_stat_t &stat = pg_map.pg_pool_sum[pool_id];
+
+ if (f) {
+ f->open_object_section("pool");
+ f->dump_string("name", pool_name);
+ f->dump_int("id", pool_id);
+ f->open_object_section("stats");
+ } else {
+ tbl << pool_name
+ << pool_id;
+ if (verbose)
+ tbl << "-";
+ }
+ dump_object_stat_sum(tbl, f, stat.stats.sum, verbose);
+ if (f)
+ f->close_section(); // stats
+ else
+ tbl << TextTable::endrow;
+
+ if (verbose) {
+ if (f)
+ f->open_array_section("categories");
+
+ for (map<string,object_stat_sum_t>::iterator it = stat.stats.cat_sum.begin();
+ it != stat.stats.cat_sum.end(); ++it) {
+ if (f) {
+ f->open_object_section(it->first.c_str());
+ } else {
+ tbl << ""
+ << ""
+ << it->first;
+ }
+ dump_object_stat_sum(tbl, f, it->second, verbose);
+ if (f)
+ f->close_section(); // category name
+ else
+ tbl << TextTable::endrow;
+ }
+ if (f)
+ f->close_section(); // categories
+ }
+ if (f)
+ f->close_section(); // pool
+ }
+ if (f)
+ f->close_section();
+ else {
+ ss << "POOLS:\n";
+ tbl.set_indent(4);
+ ss << tbl;
+ }
+}
+
+void PGMonitor::dump_fs_stats(stringstream &ss, Formatter *f, bool verbose)
+{
+ if (f) {
+ f->open_object_section("stats");
+ f->dump_int("total_space", pg_map.osd_sum.kb);
+ f->dump_int("total_used", pg_map.osd_sum.kb_used);
+ f->dump_int("total_avail", pg_map.osd_sum.kb_avail);
+ if (verbose) {
+ f->dump_int("total_objects", pg_map.pg_sum.stats.sum.num_objects);
+ }
+ f->close_section();
+ } else {
+ TextTable tbl;
+ tbl.define_column("SIZE", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("AVAIL", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("RAW USED", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("\%RAW USED", TextTable::LEFT, TextTable::LEFT);
+ if (verbose) {
+ tbl.define_column("OBJECTS", TextTable::LEFT, TextTable::LEFT);
+ }
+ tbl << stringify(si_t(pg_map.osd_sum.kb))
+ << stringify(si_t(pg_map.osd_sum.kb_avail))
+ << stringify(si_t(pg_map.osd_sum.kb_used));
+ tbl << percentify(((float)pg_map.osd_sum.kb_used / pg_map.osd_sum.kb)*100);
+ if (verbose) {
+ tbl << stringify(si_t(pg_map.pg_sum.stats.sum.num_objects));
+ }
+ tbl << TextTable::endrow;
+
+ ss << "GLOBAL:\n";
+ tbl.set_indent(4);
+ ss << tbl;
+ }
+}
+
+
void PGMonitor::dump_info(Formatter *f)
{
f->open_object_section("pgmap");
diff --git a/src/mon/PGMonitor.h b/src/mon/PGMonitor.h
index 13d75f813a5..de78e984ae9 100644
--- a/src/mon/PGMonitor.h
+++ b/src/mon/PGMonitor.h
@@ -39,6 +39,7 @@ class MMonCommand;
class MGetPoolStats;
class RatioMonitor;
+class TextTable;
class PGMonitor : public PaxosService {
public:
@@ -129,6 +130,9 @@ private:
bufferlist& rdata,
vector<const char*>& args) const;
+ void dump_object_stat_sum(TextTable &tbl, Formatter *f,
+ object_stat_sum_t &sum, bool verbose);
+
public:
PGMonitor(Monitor *mn, Paxos *p, const string& service_name)
: PaxosService(mn, p, service_name), need_check_down_pgs(false) { }
@@ -145,6 +149,9 @@ public:
void check_osd_map(epoch_t epoch);
+ void dump_pool_stats(stringstream &ss, Formatter *f, bool verbose);
+ void dump_fs_stats(stringstream &ss, Formatter *f, bool verbose);
+
void dump_info(Formatter *f);
void get_health(list<pair<health_status_t,string> >& summary,