WIP for network check
diff --git a/cfg_checker/cfg_check.py b/cfg_checker/cfg_check.py
index b2e3886..8a05771 100644
--- a/cfg_checker/cfg_check.py
+++ b/cfg_checker/cfg_check.py
@@ -9,6 +9,7 @@
from cfg_checker.clients import salt
from cfg_checker.pkg_check import CloudPackageChecker
+from cfg_checker.network_checks import NetworkChecker
pkg_dir = os.path.dirname(__file__)
pkg_dir = os.path.normpath(pkg_dir)
@@ -47,13 +48,17 @@
def net_check(args):
- print("This is net check routine")
+ netChecker = NetworkChecker()
+ netChecker.collect_network_info()
+ netChecker.print_network_report()
return
def net_report(args):
- print("This is net check routine")
+ netChecker = NetworkChecker()
+ netChecker.collect_network_info()
+ netChecker.create_html_report()
return
diff --git a/cfg_checker/network_checks.py b/cfg_checker/network_checks.py
new file mode 100644
index 0000000..56b25de
--- /dev/null
+++ b/cfg_checker/network_checks.py
@@ -0,0 +1,81 @@
+import json
+import os
+import sys
+
+from copy import deepcopy
+
+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")
+
+ return
+
+ def print_network_report(self):
+ """
+ Create text report for CLI
+
+ :return: none
+ """
+
+ return
+
+ 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")
+
+
+if __name__ == '__main__':
+ # init connection to salt and collect minion data
+ cl = NetworkChecker()
+
+ # collect data on installed packages
+ cl.collect_network_info()
+
+ # diff installed and candidates
+ # cl.collect_packages()
+
+ # report it
+ cl.create_html_report("./pkg_versions.html")
+
+ sys.exit(0)
diff --git a/cfg_checker/nodes.py b/cfg_checker/nodes.py
new file mode 100644
index 0000000..1f2b9f6
--- /dev/null
+++ b/cfg_checker/nodes.py
@@ -0,0 +1,125 @@
+import json
+import os
+import sys
+
+from copy import deepcopy
+
+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
+
+node_tmpl = {
+ 'role': '',
+ 'node_group': '',
+ 'status': const.NODE_DOWN,
+ 'pillars': {},
+ 'grains': {}
+}
+
+
+class SaltNodes(object):
+ def __init__(self):
+ logger_cli.info("### Collecting nodes for package check")
+ # simple salt rest client
+ self.salt = salt_utils.SaltRemote()
+
+ # Keys for all nodes
+ # this is not working in scope of 2016.8.3, will overide with list
+ # cls.node_keys = cls.salt.list_keys()
+
+ logger_cli.info("### Collecting node names existing in the cloud")
+ self.node_keys = {
+ 'minions': config.all_nodes
+ }
+
+ # all that answer ping
+ _active = self.salt.get_active_nodes()
+ logger_cli.debug("-> Nodes responded: {}".format(_active))
+ # just inventory for faster interaction
+ # iterate through all accepted nodes and create a dict for it
+ self.nodes = {}
+ for _name in self.node_keys['minions']:
+ _nc = utils.get_node_code(_name)
+ _rmap = const.all_roles_map
+ _role = _rmap[_nc] if _nc in _rmap else 'unknown'
+ _status = const.NODE_UP if _name in _active else const.NODE_DOWN
+
+ self.nodes[_name] = deepcopy(node_tmpl)
+ self.nodes[_name]['node_group'] = _nc
+ self.nodes[_name]['role'] = _role
+ self.nodes[_name]['status'] = _status
+
+ logger_cli.info("-> {} nodes collected".format(len(self.nodes)))
+
+ def get_nodes(self):
+ return self.nodes
+
+ def execute_script(self, script_filename, args=[]):
+ # form an all nodes compound string to use in salt
+ _active_nodes_string = self.salt.compound_string_from_list(
+ filter(
+ lambda nd: self.nodes[nd]['status'] == const.NODE_UP,
+ self.nodes
+ )
+ )
+ # Prepare script
+ _p = os.path.join(pkg_dir, 'scripts', script_filename)
+ with open(_p, 'rt') as fd:
+ _script = fd.read().splitlines()
+ _storage_path = os.path.join(
+ config.salt_file_root, config.salt_scripts_folder
+ )
+ logger_cli.debug(
+ "# Uploading script {} to master's file cache folder: '{}'".format(
+ script_filename,
+ _storage_path
+ )
+ )
+ _result = self.salt.mkdir("cfg01*", _storage_path)
+ # Form cache, source and target path
+ _cache_path = os.path.join(_storage_path, script_filename)
+ _source_path = os.path.join(
+ 'salt://',
+ config.salt_scripts_folder,
+ script_filename
+ )
+ _target_path = os.path.join(
+ '/root',
+ config.salt_scripts_folder,
+ script_filename
+ )
+
+ logger_cli.debug("# Creating file in cache '{}'".format(_cache_path))
+ _result = self.salt.f_touch_master(_cache_path)
+ _result = self.salt.f_append_master(_cache_path, _script)
+ # command salt to copy file to minions
+ logger_cli.debug("# Creating script target folder '{}'".format(_cache_path))
+ _result = self.salt.mkdir(
+ _active_nodes_string,
+ os.path.join(
+ '/root',
+ config.salt_scripts_folder
+ ),
+ tgt_type="compound"
+ )
+ logger_cli.info("-> Running script to all active nodes")
+ _result = self.salt.get_file(
+ _active_nodes_string,
+ _source_path,
+ _target_path,
+ tgt_type="compound"
+ )
+ # execute pkg collecting script
+ logger.debug("Running script to all nodes")
+ # handle results for each node
+ _script_arguments = " ".join(args) if args else ""
+ _result = self.salt.cmd(
+ _active_nodes_string,
+ 'cmd.run',
+ param='python {} {}'.format(_target_path, _script_arguments),
+ expr_form="compound"
+ )
+
+ # TODO: Handle error result
+
+ return _result
diff --git a/cfg_checker/pkg_check.py b/cfg_checker/pkg_check.py
index fe34f60..e9c312e 100644
--- a/cfg_checker/pkg_check.py
+++ b/cfg_checker/pkg_check.py
@@ -9,50 +9,10 @@
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
-
-node_tmpl = {
- 'role': '',
- 'node_group': '',
- 'status': const.NODE_DOWN,
- 'pillars': {},
- 'grains': {}
-}
+from cfg_checker.nodes import SaltNodes, node_tmpl
-class CloudPackageChecker(object):
- def __init__(self):
- logger_cli.info("### Collecting nodes for package check")
- # simple salt rest client
- self.salt = salt_utils.SaltRemote()
-
- # Keys for all nodes
- # this is not working in scope of 2016.8.3, will overide with list
- # cls.node_keys = cls.salt.list_keys()
-
- logger_cli.info("### Collecting node names existing in the cloud")
- self.node_keys = {
- 'minions': config.all_nodes
- }
-
- # all that answer ping
- _active = self.salt.get_active_nodes()
- logger_cli.debug("-> Nodes responded: {}".format(_active))
- # just inventory for faster interaction
- # iterate through all accepted nodes and create a dict for it
- self.nodes = {}
- for _name in self.node_keys['minions']:
- _nc = utils.get_node_code(_name)
- _rmap = const.all_roles_map
- _role = _rmap[_nc] if _nc in _rmap else 'unknown'
- _status = const.NODE_UP if _name in _active else const.NODE_DOWN
-
- self.nodes[_name] = deepcopy(node_tmpl)
- self.nodes[_name]['node_group'] = _nc
- self.nodes[_name]['role'] = _role
- self.nodes[_name]['status'] = _status
-
- logger_cli.info("-> {} nodes collected".format(len(self.nodes)))
-
+class CloudPackageChecker(SaltNodes):
def collect_installed_packages(self):
"""
Collect installed packages on each node
@@ -61,70 +21,8 @@
:return: none
"""
logger_cli.info("### Collecting installed packages")
- # form an all nodes compound string to use in salt
- _active_nodes_string = self.salt.compound_string_from_list(
- filter(
- lambda nd: self.nodes[nd]['status'] == const.NODE_UP,
- self.nodes
- )
- )
- # Prepare script
- _script_filename = "pkg_versions.py"
- _p = os.path.join(pkg_dir, 'scripts', _script_filename)
- with open(_p, 'rt') as fd:
- _script = fd.read().splitlines()
- _storage_path = os.path.join(
- config.salt_file_root, config.salt_scripts_folder
- )
- logger_cli.debug(
- "# Uploading script {} to master's file cache folder: '{}'".format(
- _script_filename,
- _storage_path
- )
- )
- _result = self.salt.mkdir("cfg01*", _storage_path)
- # Form cache, source and target path
- _cache_path = os.path.join(_storage_path, _script_filename)
- _source_path = os.path.join(
- 'salt://',
- config.salt_scripts_folder,
- _script_filename
- )
- _target_path = os.path.join(
- '/root',
- config.salt_scripts_folder,
- _script_filename
- )
+ _result = self.execute_script("pkg_versions.py")
- logger_cli.debug("# Creating file in cache '{}'".format(_cache_path))
- _result = self.salt.f_touch_master(_cache_path)
- _result = self.salt.f_append_master(_cache_path, _script)
- # command salt to copy file to minions
- logger_cli.debug("# Creating script target folder '{}'".format(_cache_path))
- _result = self.salt.mkdir(
- _active_nodes_string,
- os.path.join(
- '/root',
- config.salt_scripts_folder
- ),
- tgt_type="compound"
- )
- logger_cli.info("-> Running script to all active nodes")
- _result = self.salt.get_file(
- _active_nodes_string,
- _source_path,
- _target_path,
- tgt_type="compound"
- )
- # execute pkg collecting script
- logger.debug("Running script to all nodes")
- # handle results for each node
- _result = self.salt.cmd(
- _active_nodes_string,
- 'cmd.run',
- param='python {}'.format(_target_path),
- expr_form="compound"
- )
for key in self.nodes.keys():
# due to much data to be passed from salt, it is happening in order
if key in _result:
diff --git a/cfg_checker/reporter.py b/cfg_checker/reporter.py
index 3b21894..a0eb1b3 100644
--- a/cfg_checker/reporter.py
+++ b/cfg_checker/reporter.py
@@ -156,6 +156,14 @@
data['counters']['mdl_diff'] = len(data["diffs"].keys())
+class HTMLNetworkReport(_TMPLBase):
+ tmpl = "network_check_tmpl.j2"
+
+ def _extend_data(self, data):
+
+ return
+
+
class ReportToFile(object):
def __init__(self, report, target):
self.report = report