Ceph info and report OSD configuration

 - Added OSD configuration gathering
 - Uniq values filtering

 Related-PROD: PROD-36669

Change-Id: I7a2ef144554d892d06c0f05f978a512ba156360a
diff --git a/cfg_checker/modules/ceph/__init__.py b/cfg_checker/modules/ceph/__init__.py
index 85d4273..3f726f8 100644
--- a/cfg_checker/modules/ceph/__init__.py
+++ b/cfg_checker/modules/ceph/__init__.py
@@ -165,7 +165,8 @@
     ceph_bench_parser.add_argument(
         '--offset-increment',
         metavar="offset_increment", default="500M",
-        help="Offset to be used in 'read' and 'write' modes if multiple jobs used"
+        help="Offset to be used in 'read' and 'write' modes if multiple jobs "
+             "used"
         "Default: '500M'"
     )
 
@@ -184,6 +185,7 @@
 
     logger_cli.info("# Collecting Ceph cluster information")
     ceph_info.gather_info()
+    ceph_info.gather_osd_configs()
 
     # Debug, enable if needed to debug report generation
     # without actuall data collecting each time
@@ -211,6 +213,7 @@
     # ceph_info.load_info()
     # end debug
     ceph_info.gather_info()
+    ceph_info.gather_osd_configs()
     ceph_info.get_transposed_latency_table()
     ceph_info.get_latest_health_readout()
     ceph_info.create_html_report(_filename)
diff --git a/cfg_checker/modules/ceph/info.py b/cfg_checker/modules/ceph/info.py
index f6d5758..2a23936 100644
--- a/cfg_checker/modules/ceph/info.py
+++ b/cfg_checker/modules/ceph/info.py
@@ -594,3 +594,63 @@
         )
 
         return
+
+    def gather_osd_configs(self):
+        _total_osd = len(self.ceph_info["ceph_osd_df"]["data"]["nodes"])
+        logger_cli.info(
+            "-> Gathering OSD configuration ({})".format(_total_osd)
+        )
+        # Shortcuts
+        # _c = self._safe_tools_cmd
+        _cj = self._safe_get_cmd_output_as_json
+        _progress = Progress(_total_osd)
+        _idx = 1
+        _cfgs = {}
+        for _osd in self.ceph_info["ceph_osd_df"]["data"]["nodes"]:
+            _progress.write_progress(_idx, note=_osd["name"])
+            _cfgs[_osd["name"]] = _cj(
+                "ceph config show-with-defaults -f json {}".format(
+                    _osd["name"]
+                )
+            )
+            _idx += 1
+        _progress.end()
+
+        # Process configs
+        _base = {}
+        _uniq = {}
+        logger_cli.info("-> Filtering config values")
+        _progress = Progress(_total_osd)
+        _idx = 1
+        for _osd, _data in _cfgs.items():
+            _progress.write_progress(_idx, note=_osd)
+            for _o in _data:
+                _name = _o.pop("name")
+                if not _o["value"]:
+                    _o["value"] = "-"
+                if _name not in _base:
+                    _base[_name] = _o
+                elif _base[_name]["value"] != _o["value"]:
+                    _progress.clearline()
+                    logger_cli.info(
+                        "...specific value for {} (src: '{}'): {}={}".format(
+                            _osd,
+                            _o["source"],
+                            _name,
+                            _o["value"]
+                        )
+                    )
+                    _uniq[_osd] = {
+                        _name: _o
+                    }
+            _idx += 1
+        _progress.end()
+        self._add_ceph_info_item(
+            "osd_config_data",
+            "OSD Configuration values",
+            {
+                "common": _base,
+                "uniq": _uniq
+            }
+        )
+        return