cfg-checker ceph bench module alpha version

 - Ceph benchmark report (beta)
 - Updated result time choosing. Now results reported based on start time
 - New methods for listing
 - Cleanup-only mode
 - Unified results processing
 - Additional ceph info gather
 - Experimental barchart graph example

Fixes:
 - Kube API client recreated each time for stability (HTTP/WebSocket specifics)
 - args naming fixes
 -

Change-Id: Id541f789a00ab4ee827603c5b6f7f07899aaa7c5
diff --git a/cfg_checker/agent/fio_runner.py b/cfg_checker/agent/fio_runner.py
index c8488af..3cc6ca2 100644
--- a/cfg_checker/agent/fio_runner.py
+++ b/cfg_checker/agent/fio_runner.py
@@ -257,6 +257,7 @@
             self._fio_options_common["ioengine"] = "posixaio"
         # Thread finish marker
         self.finished = False
+        self.testrun_starttime = None
         self.scheduled_datetime = None
 
     def update_options(self, _dict):
@@ -296,8 +297,8 @@
         _q = queue.Queue()
         self.fiorun = ShellThread(_cmd, _q)
         # Check if schedule is set
+        _now = datetime.now(timezone.utc)
         if self.scheduled_datetime:
-            _now = datetime.now(timezone.utc)
             logger.debug(
                 "waiting for '{}', now is '{}', total of {} sec left".format(
                     self.scheduled_datetime.strftime(_datetime_fmt),
@@ -306,6 +307,8 @@
                 )
             )
             wait_until(self.scheduled_datetime)
+        else:
+            self.testrun_starttime = _now.strftime(_datetime_fmt)
         self.fiorun.run_shell()
         _raw = []
         _start = -1
@@ -360,11 +363,13 @@
                 break
             sleep(0.1)
         # Save status to results dictionary
-        self.results[get_time(timestamp=self.testrun["timestamp"])] = {
+        self.results[self.testrun_starttime] = {
             "result": self.testrun,
             "timeline": self.timeline
         }
         self.finished = True
+        self.scheduled_datetime = None
+        self.testrun_starttime = None
         return
 
     def healthcheck(self):
@@ -511,9 +516,9 @@
             raise CheckerException("Parameter missing: 'scheduled_to'")
         else:
             # set time and get rid of it from options
-            _time = options.pop("scheduled_to")
+            self.fio.testrun_starttime = options.pop("scheduled_to")
             self.fio.scheduled_datetime = datetime.strptime(
-                _time,
+                self.fio.testrun_starttime,
                 _datetime_fmt
             )
         # Fill options
@@ -612,7 +617,7 @@
     _opts["readwrite"] = "read"
     _opts["ramp_time"] = "1s"
     _opts["runtime"] = "5s"
-    _opts["scheduled_to"] = "11/13/2021, 23:03:30+0000"
+    _opts["scheduled_to"] = "11/23/2021, 21:48:20+0000"
     _shell.do_scheduledrun(_opts)
     _shell()
     _times = _shell.get_resultlist()
@@ -627,8 +632,8 @@
     _opts["readwrite"] = "read"
     _opts["ramp_time"] = "1s"
     _opts["runtime"] = "10s"
-    _opts["scheduled_to"] = "11/13/2021, 23:04:20+0000"
-    _shell.do_scheduledrun(_opts)
+    # _opts["scheduled_to"] = "11/23/2021, 21:40:30+0000"
+    _shell.do_singlerun(_opts)
     _shell()
     _times = _shell.get_resultlist()
     print("# results:\n{}".format("\n".join(_times)))