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/common/file_utils.py b/cfg_checker/common/file_utils.py
index 6fbb675..faf7cf0 100644
--- a/cfg_checker/common/file_utils.py
+++ b/cfg_checker/common/file_utils.py
@@ -102,7 +102,7 @@
         os.mkdir(_folder)
         return "... folder '{}' created".format(_folder)
     else:
-        return "... folder is at '{}'".format(_folder)
+        return "... folder exists at '{}'".format(_folder)
 
 
 def ensure_folder_removed(_folder):
diff --git a/cfg_checker/common/kube_utils.py b/cfg_checker/common/kube_utils.py
index 22eee30..3e15095 100644
--- a/cfg_checker/common/kube_utils.py
+++ b/cfg_checker/common/kube_utils.py
@@ -206,7 +206,6 @@
 class KubeRemote(KubeApi):
     def __init__(self, config):
         super(KubeRemote, self).__init__(config)
-        self._coreV1 = None
         self._appsV1 = None
         self._podV1 = None
         self._custom = None
@@ -219,12 +218,10 @@
 
     @property
     def CoreV1(self):
-        if not self._coreV1:
-            if self.is_local:
-                self._coreV1 = kclient.CoreV1Api(kclient.ApiClient())
-            else:
-                self._coreV1 = kclient.CoreV1Api(kclient.ApiClient(self.kConf))
-        return self._coreV1
+        if self.is_local:
+            return kclient.CoreV1Api(kclient.ApiClient())
+        else:
+            return kclient.CoreV1Api(kclient.ApiClient(self.kConf))
 
     @property
     def AppsV1(self):
@@ -377,6 +374,7 @@
 
         return _pods
 
+    @retry(ApiException, initial_wait=5)
     def exec_on_target_pod(
         self,
         cmd,
@@ -425,6 +423,7 @@
         cmd = cmd if isinstance(cmd, list) else cmd.split()
         if arguments:
             cmd += [arguments]
+        # Make sure that CoreV1 is fresh before calling it
         _pod_stream = stream(
             self.CoreV1.connect_get_namespaced_pod_exec,
             _pname,
@@ -453,8 +452,6 @@
             )
             if not _output:
                 _output = _error
-        # Force recreate of api objects
-        self._coreV1 = None
         # Send output
         return _output
 
@@ -596,7 +593,7 @@
 
         return []
 
-    @retry(ApiException)
+    @retry(ApiException, initial_wait=5)
     def get_pods_for_daemonset(self, ds):
         # get all pod names for daemonset
         logger_cli.debug(
@@ -612,6 +609,7 @@
         )
         return _pods
 
+    @retry(ApiException, initial_wait=5)
     def put_string_buffer_to_pod_as_textfile(
         self,
         pod_name,
@@ -653,15 +651,12 @@
                 logger_cli.debug("... STDERR: %s" % response.read_stderr())
             if commands:
                 c = commands.pop(0)
-                logger_cli.debug("... running command... {}\n".format(c))
+                logger_cli.debug("... running command... {}".format(c))
                 response.write_stdin(str(c, encoding='utf-8'))
             else:
                 break
         response.close()
 
-        # Force recreate of Api objects
-        self._coreV1 = None
-
         return
 
     def get_custom_resource(self, group, version, plural):
@@ -824,6 +819,12 @@
             name
         )
 
+    def list_pods(self, ns, label_str=None):
+        return self.CoreV1.list_namespaced_pod(
+            ns,
+            label_selector=label_str
+        )
+
     def get_svc_by_name_and_ns(self, name, ns):
         return self.safe_get_item_by_name(
             self.CoreV1.list_namespaced_service(
@@ -833,6 +834,12 @@
             name
         )
 
+    def list_svc(self, ns, label_str=None):
+        return self.CoreV1.list_namespaced_service(
+            ns,
+            label_selector=label_str
+        )
+
     def get_pvc_by_name_and_ns(self, name, ns):
         return self.safe_get_item_by_name(
             self.CoreV1.list_namespaced_persistent_volume_claim(
@@ -842,6 +849,12 @@
             name
         )
 
+    def list_pvc(self, ns, label_str=None):
+        return self.CoreV1.list_namespaced_persistent_volume_claim(
+            ns,
+            label_selector=label_str
+        )
+
     def get_pv_by_name(self, name):
         return self.safe_get_item_by_name(
             self.CoreV1.list_persistent_volume(
@@ -850,6 +863,11 @@
             name
         )
 
+    def list_pv(self, label_str=None):
+        return self.CoreV1.list_persistent_volume(
+            label_selector=label_str
+        )
+
     def wait_for_phase(self, ttype, name, ns, phase_list, timeout=120):
         logger_cli.debug(
             "... waiting '{}'s until {} is '{}'".format(