From: Mohamad Gebai Date: Tue, 23 Jan 2018 13:56:36 +0000 (-0500) Subject: mgr/iostat: implement 'ceph iostat' as a mgr plugin X-Git-Tag: v13.1.0~254^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=40983f7f2005078677bce76e93eccdd3d74cf36d;p=ceph.git mgr/iostat: implement 'ceph iostat' as a mgr plugin Allow a mgr module to fetch 'io_rate' to access pg_sum_delta, which holds the IO activity recently completed by the OSDs. Signed-off-by: Mohamad Gebai --- diff --git a/src/ceph.in b/src/ceph.in index 0814b0bd1f97..7484a54dfc8f 100755 --- a/src/ceph.in +++ b/src/ceph.in @@ -20,6 +20,7 @@ Foundation. See file COPYING. """ from __future__ import print_function +from time import sleep import codecs import os import sys @@ -1053,6 +1054,16 @@ def main(): print('error handling command target: {0}'.format(e), file=sys.stderr) return 1 + # ceph iostat + if len(childargs) > 0 and childargs[0] == 'iostat': + def call_iostat(): + while 1: + subprocess.call([sys.argv[0], 'mgr', 'iostat']) + sleep(1) + + run_in_thread(call_iostat) + return 1 + # Repulsive hack to handle tell: lop off 'tell' and target # and validate the rest of the command. 'target' is already # determined in our callers, so it's ok to remove it here. diff --git a/src/mgr/ActivePyModules.cc b/src/mgr/ActivePyModules.cc index 08d907ec556c..215ae3ca1915 100644 --- a/src/mgr/ActivePyModules.cc +++ b/src/mgr/ActivePyModules.cc @@ -282,6 +282,14 @@ PyObject *ActivePyModules::get_python(const std::string &what) } ); return f.get(); + } else if (what == "io_rate") { + PyFormatter f; + cluster_state.with_pgmap( + [&f](const PGMap &pg_map) { + pg_map.dump_delta(&f); + } + ); + return f.get(); } else if (what == "df") { PyFormatter f; diff --git a/src/mon/PGMap.cc b/src/mon/PGMap.cc index 353743771492..4e1d6541898b 100644 --- a/src/mon/PGMap.cc +++ b/src/mon/PGMap.cc @@ -1395,6 +1395,7 @@ void PGMap::dump_delta(Formatter *f) const { f->open_object_section("pg_stats_delta"); pg_sum_delta.dump(f); + f->dump_stream("stamp_delta") << stamp_delta; f->close_section(); } diff --git a/src/pybind/mgr/iostat/__init__.py b/src/pybind/mgr/iostat/__init__.py new file mode 100644 index 000000000000..8f210ac9247e --- /dev/null +++ b/src/pybind/mgr/iostat/__init__.py @@ -0,0 +1 @@ +from .module import Module diff --git a/src/pybind/mgr/iostat/module.py b/src/pybind/mgr/iostat/module.py new file mode 100644 index 000000000000..65b6e5c4884a --- /dev/null +++ b/src/pybind/mgr/iostat/module.py @@ -0,0 +1,35 @@ + +from mgr_module import MgrModule + + +class Module(MgrModule): + COMMANDS = [ + { + "cmd": "mgr iostat", + "desc": "Get IO rates", + "perm": "r" + } + ] + + + def __init__(self, *args, **kwargs): + super(Module, self).__init__(*args, **kwargs) + + + def handle_command(self, command): + rd = 0 + wr = 0 + ops = 0 + + if command['prefix'] == 'mgr iostat': + r = self.get('io_rate') + + stamp_delta = float(r['pg_stats_delta']['stamp_delta']) + if (stamp_delta > 0): + rd = int(r['pg_stats_delta']['stat_sum']['num_read_kb']) / stamp_delta + wr = int(r['pg_stats_delta']['stat_sum']['num_write_kb']) / stamp_delta + ops = ( int(r['pg_stats_delta']['stat_sum']['num_write']) + int(r['pg_stats_delta']['stat_sum']['num_read']) ) / stamp_delta + + ret = "wr: {0} kB/s, rd: {1} kB/s, iops: {2}".format(str(int(wr)), str(int(rd)), str(int(ops))) + + return 0, '', ret diff --git a/src/pybind/mgr/mgr_module.py b/src/pybind/mgr/mgr_module.py index 480fc8586d0f..b51952ebd18e 100644 --- a/src/pybind/mgr/mgr_module.py +++ b/src/pybind/mgr/mgr_module.py @@ -314,7 +314,7 @@ class MgrModule(ceph_module.BaseMgrModule): :param str data_name: Valid things to fetch are osd_crush_map_text, osd_map, osd_map_tree, osd_map_crush, config, mon_map, fs_map, - osd_metadata, pg_summary, df, osd_stats, health, mon_status. + osd_metadata, pg_summary, io_rate, pg_dump, df, osd_stats, health, mon_status. Note: All these structures have their own JSON representations: experiment