Module refactoring and dynamic loading
diff --git a/cfg_checker/modules/network/checker.py b/cfg_checker/modules/network/checker.py
new file mode 100644
index 0000000..03a48de
--- /dev/null
+++ b/cfg_checker/modules/network/checker.py
@@ -0,0 +1,129 @@
+import json
+import os
+import sys
+import ipaddress
+
+from copy import deepcopy
+
+from cfg_checker import reporter
+from cfg_checker.common import utils, const
+from cfg_checker.common import config, logger, logger_cli, pkg_dir
+from cfg_checker.common import salt_utils
+from cfg_checker.nodes import SaltNodes, node_tmpl
+
+
+class NetworkChecker(SaltNodes):
+ def collect_network_info(self):
+ """
+ Collects info on the network using ifs_data.py script
+
+ :return: none
+ """
+ logger_cli.info("### Collecting network data")
+ _result = self.execute_script("ifs_data.py", args=["json"])
+
+ for key in self.nodes.keys():
+ # due to much data to be passed from salt, it is happening in order
+ if key in _result:
+ _text = _result[key]
+ _dict = json.loads(_text[_text.find('{'):])
+ self.nodes[key]['networks'] = _dict
+ else:
+ self.nodes[key]['networks'] = {}
+ logger_cli.debug("# {} has {} networks".format(
+ key,
+ len(self.nodes[key]['networks'].keys())
+ ))
+ logger_cli.info("-> done collecting networks data")
+
+ # dump collected data to speed up coding
+ # with open('dump.json', 'w+') as ff:
+ # ff.write(json.dumps(self.nodes))
+
+ # load dump data
+ # with open('dump.json', 'r') as ff:
+ # _nodes = json.loads(ff.read())
+
+ logger_cli.info("### Building network tree")
+ # match physical interfaces by MAC addresses
+ _all_nets = {}
+ for host, node_data in self.nodes.iteritems():
+ for net_name, net_data in node_data['networks'].iteritems():
+ # get ips and calculate subnets
+ if net_name == 'lo':
+ continue
+ _ip4s = net_data['ipv4']
+ for _ip_str in _ip4s.keys():
+ _if = ipaddress.IPv4Interface(_ip_str)
+ if not any(_if.ip in net for net in _all_nets.keys()):
+ # IP not fits into existing networks
+ if _if.network not in _all_nets.keys():
+ _all_nets[_if.network] = {}
+
+ _all_nets[_if.network][host] = {}
+ _all_nets[_if.network][host]['text'] = \
+ "{0:30}: {1:19} {2:5} {3:4}".format(
+ net_name,
+ str(_if.ip),
+ net_data['mtu'],
+ net_data['state']
+ )
+ _all_nets[_if.network][host]['if_data'] = net_data
+ else:
+ # There is a network that ip fits into
+ for _net in _all_nets.keys():
+ if _if.ip in _net:
+ if host not in _all_nets[_net]:
+ _all_nets[_net][host] = {}
+ _all_nets[_net][host]['text'] = \
+ "{0:30}: {1:19} {2:5} {3:4}".format(
+ net_name,
+ str(_if.ip),
+ net_data['mtu'],
+ net_data['state']
+ )
+ _all_nets[_net][host]['if_data'] = \
+ net_data
+
+ # save collected info
+ self.all_networks = _all_nets
+
+ # Get networks from reclass
+ # TODO:
+
+ return
+
+ def print_network_report(self):
+ """
+ Create text report for CLI
+
+ :return: none
+ """
+ for network, nodes in self.all_networks.iteritems():
+ logger_cli.info("-> {}".format(str(network)))
+ names = sorted(nodes.keys())
+
+ for hostname in names:
+ logger_cli.info(
+ "\t{0:10} {1}".format(
+ hostname.split('.')[0],
+ nodes[hostname]['text']
+ )
+ )
+
+ def create_html_report(self, filename):
+ """
+ Create static html showing network schema-like report
+
+ :return: none
+ """
+ logger_cli.info("### Generating report to '{}'".format(filename))
+ _report = reporter.ReportToFile(
+ reporter.HTMLNetworkReport(),
+ filename
+ )
+ _report({
+ "nodes": self.nodes,
+ "diffs": {}
+ })
+ logger_cli.info("-> Done")