Network check HTML report

- uniform map generation
- POC for additional checks on env

Change-Id: I52edcc94f4d9826cbfb1159e5311514097a15f62
Related-PROD: PROD-32792
diff --git a/cfg_checker/nodes.py b/cfg_checker/nodes.py
index 5e535b4..ca4e261 100644
--- a/cfg_checker/nodes.py
+++ b/cfg_checker/nodes.py
@@ -140,6 +140,53 @@
             self.gather_node_info()
         return self.nodes
 
+    def get_info(self):
+        _info = {
+           'mcp_release': self.mcp_release,
+           'openstack_release': self.openstack_release
+        }
+        return _info
+
+    def get_cmd_for_nodes(self, cmd, target_key, target_dict=None):
+        """Function runs. cmd.run and parses result into place
+        or into dict structure provided
+
+        :return: no return value, data pulished internally
+        """
+        logger_cli.debug(
+            "... collecting results for '{}'".format(cmd)
+        )
+        if target_dict:
+            _nodes = target_dict
+        else:
+            _nodes = self.nodes
+        _result = self.execute_cmd_on_active_nodes(cmd)
+        for node, data in _nodes.iteritems():
+            if node in self.skip_list:
+                logger_cli.debug(
+                    "... '{}' skipped while collecting '{}'".format(
+                        node,
+                        cmd
+                    )
+                )
+                continue
+            # Prepare target key
+            if target_key not in data:
+                data[target_key] = None
+            # Save data
+            if data['status'] == const.NODE_DOWN:
+                data[target_key] = None
+            elif not _result[node]:
+                logger_cli.debug(
+                    "... '{}' not responded after '{}'".format(
+                        node,
+                        config.salt_timeout
+                    )
+                )
+                data[target_key] = None
+            else:
+                data[target_key] = _result[node]
+
     def get_specific_pillar_for_nodes(self, pillar_path):
         """Function gets pillars on given path for all nodes
 
@@ -322,6 +369,20 @@
         self.not_responded = [_n for _n in _r.keys() if not _r[_n]]
         return _r
 
+    def execute_cmd_on_active_nodes(self, cmd):
+        # execute cmd
+        self.not_responded = []
+        _r = self.salt.cmd(
+            self.active_nodes_compound,
+            'cmd.run',
+            param=cmd,
+            expr_form="compound"
+        )
+
+        # all false returns means that there is no response
+        self.not_responded = [_n for _n in _r.keys() if not _r[_n]]
+        return _r
+
     def is_node_available(self, node, log=True):
         if node in self.skip_list:
             if log: