Skip to content

Commit

Permalink
mgr/cli lightweight get method api call
Browse files Browse the repository at this point in the history
Fixes: https://tracker.ceph.com/issues/50311
Signed-off-by: Waad AlKhoury <walkhour@redhat.com>
  • Loading branch information
Waad AlKhoury committed Jun 21, 2021
1 parent 8343471 commit 01bd10d
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/pybind/mgr/cli_api/__init__.py
@@ -0,0 +1,7 @@
import os

if 'UNITTEST' in os.environ:
import tests


from .module import CLI
96 changes: 96 additions & 0 deletions src/pybind/mgr/cli_api/module.py
@@ -0,0 +1,96 @@
import json
import logging
import threading
import time
from functools import partial
from threading import Event, Lock
from queue import Queue

from mgr_module import CLICommand, HandleCommandResult, MgrModule

logger = logging.getLogger()

class CLI(MgrModule):

NATIVE_OPTIONS = [
'mgr_tick_period',
]

@CLICommand('mgr api get')
def api_get(self, arg: str):
'''
Called by the plugin to fetch named cluster-wide objects from ceph-mgr.
: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, io_rate, pg_dump, df, osd_stats,
health, mon_status, devices, device <devid>, pg_stats,
pool_stats, pg_ready, osd_ping_times.
Note:
All these structures have their own JSON representations: experiment
or look at the C++ ``dump()`` methods to learn about them.
'''
t1_start = time.time()
str_arg = self.get(arg)
t1_end = time.time()
time_final = (t1_end - t1_start)
return HandleCommandResult(0, json.dumps(str_arg), str(time_final))

@CLICommand('mgr api benchmark get')
def api_get_benchmark(self, arg: str, number_of_total_calls: int,
number_of_parallel_calls: int):
benchmark_runner = ThreadedBenchmarkRunner(number_of_total_calls,
number_of_parallel_calls)
benchmark_runner.start(partial(self.get,arg))
benchmark_runner.join()
stats = benchmark_runner.get_stats()
return HandleCommandResult(0, json.dumps(stats), "")

class ThreadedBenchmarkRunner:
def __init__(self,number_of_total_calls, number_of_parallel_calls):
self.number_of_parallel_calls = number_of_parallel_calls
self.number_of_total_calls = number_of_total_calls
self.threads = []
self.jobs = Queue()
self.time = 0
self.self_time = []
self.lock = threading.Lock()

def start(self,fn):
if (self.number_of_total_calls and self.number_of_parallel_calls):
for threadID in range(self.number_of_parallel_calls):
new_thread = threading.Thread(target=ThreadedBenchmarkRunner.timer,
args=(self,self.jobs,fn,))
self.threads.append(new_thread)
for jobsID in range(self.number_of_total_calls):
self.jobs.put(jobsID)
for thread in self.threads:
thread.start()
else:
raise BenchmarkException("Number of Total and number of parallel calls must be greater than 0")

def join(self):
for thread in self.threads:
thread.join()

def get_stats(self):
stats = {
"avg": (self.time / self.number_of_total_calls),
"min": min(self.self_time),
"max": max(self.self_time)
}
return stats

def timer(self,jobs,func):
self.lock.acquire()
while not self.jobs.empty():
value = jobs.get()
t1 = time.time()
func()
t2 = time.time()
self.self_time.append(t2 - t1)
self.time += (t2 - t1)
self.jobs.task_done()
self.lock.release()

class BenchmarkException(Exception):
pass
Empty file.
40 changes: 40 additions & 0 deletions src/pybind/mgr/cli_api/tests/test_cliapi.py
@@ -0,0 +1,40 @@
from pytest import approx
import os
import unittest

from ..module import ThreadedBenchmarkRunner, BenchmarkException

class ThreadedBenchmarkRunnerTest(unittest.TestCase):
def test_number_of_calls_on_start_fail(self):
c = ThreadedBenchmarkRunner(0,10)
with self.assertRaises(BenchmarkException):
c.start(None)

def test_number_of_parallel_calls_on_start_fail(self):
c = ThreadedBenchmarkRunner(10,0)
with self.assertRaises(BenchmarkException):
c.start(None)

def test_number_of_parallel_calls_on_start_work(self):
c = ThreadedBenchmarkRunner(10,10)
def dummy_function():
pass
c.start(dummy_function)
assert(len(c.self_time) > 0)
assert(sum(c.self_time) > 0)

def test_get_stats_work(self):
c = ThreadedBenchmarkRunner(10,10)
def dummy_function():
for i in range(10):
pass
c.start(dummy_function)
stats = c.get_stats()
assert(stats['avg'] > 0)
assert(stats['min'] > 0)
assert(stats['max'] > 0)





1 change: 1 addition & 0 deletions src/pybind/mgr/tox.ini
Expand Up @@ -47,6 +47,7 @@ commands =
insights/ \
pg_autoscaler/ \
progress/ \
cli_api/ \
snap_schedule}

[testenv:mypy]
Expand Down

0 comments on commit 01bd10d

Please sign in to comment.