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/modules/network/__init__.py b/cfg_checker/modules/network/__init__.py
index 6b06022..6b9013a 100644
--- a/cfg_checker/modules/network/__init__.py
+++ b/cfg_checker/modules/network/__init__.py
@@ -66,15 +66,6 @@
return _parser
-def _prepare_map():
- _mapper = mapper.NetworkMapper()
- _mapper.map_network(_mapper.RECLASS)
- _mapper.map_network(_mapper.RUNTIME)
- _mapper.map_network(_mapper.CONFIG)
-
- return _mapper
-
-
def do_check(args):
# Net Checks
# should not print map, etc...
@@ -104,6 +95,10 @@
_filename = args_utils.get_arg(args, 'html')
netChecker = checker.NetworkChecker()
+ netChecker.check_networks(map=False)
+
+ # save what was collected
+ netChecker.errors.save_iteration_data()
netChecker.create_html_report(_filename)
return
@@ -114,7 +109,9 @@
# Should generate network map to console or HTML
logger_cli.info("# Network report")
- networkMap = _prepare_map()
+ networkMap = mapper.NetworkMapper()
+ networkMap.prepare_all_maps()
+ networkMap.create_map()
networkMap.print_map()
return
diff --git a/cfg_checker/modules/network/checker.py b/cfg_checker/modules/network/checker.py
index 89db6ba..acd3bb1 100644
--- a/cfg_checker/modules/network/checker.py
+++ b/cfg_checker/modules/network/checker.py
@@ -10,11 +10,13 @@
self.errors = NetworkErrors()
self.mapper = NetworkMapper(self.errors)
- def check_networks(self):
+ def check_networks(self, map=True):
self.mapper.map_network(self.mapper.RECLASS)
self.mapper.map_network(self.mapper.RUNTIME)
- self.mapper.print_map()
+ self.mapper.create_map()
+ if map:
+ self.mapper.print_map()
def print_summary(self):
logger_cli.info(self.errors.get_summary(print_zeros=False))
@@ -39,10 +41,10 @@
filename
)
_report({
- "nodes": self.nodes,
- "network": {},
- "mcp_release": self.mcp_release,
- "openstack_release": self.openstack_release
+ "nodes": self.mapper.nodes,
+ "map": self.mapper.map,
+ "mcp_release": self.mapper.cluster['mcp_release'],
+ "openstack_release": self.mapper.cluster['openstack_release']
})
logger_cli.info("-> Done")
diff --git a/cfg_checker/modules/network/mapper.py b/cfg_checker/modules/network/mapper.py
index c3e3b73..ba9a256 100644
--- a/cfg_checker/modules/network/mapper.py
+++ b/cfg_checker/modules/network/mapper.py
@@ -36,6 +36,7 @@
# init networks and nodes
self.networks = {}
self.nodes = salt_master.get_nodes()
+ self.cluster = salt_master.get_info()
# init and pre-populate interfaces
self.interfaces = {k: {} for k in self.nodes}
# Init errors class
@@ -45,6 +46,11 @@
logger_cli.debug("... init error logs folder")
self.errors = NetworkErrors()
+ def prepare_all_maps(self):
+ self.map_network(self.RECLASS)
+ self.map_network(self.RUNTIME)
+ self.map_network(self.CONFIG)
+
# adding net data to tree
def _add_data(self, _list, _n, _h, _d):
if _n not in _list:
@@ -253,32 +259,23 @@
self.networks[source] = _networks
return _networks
- def print_map(self):
- """
- Create text report for CLI
+ def create_map(self):
+ """Create all needed elements for map output
:return: none
"""
_runtime = self.networks[self.RUNTIME]
_reclass = self.networks[self.RECLASS]
- logger_cli.info("# Networks")
- logger_cli.info(
- " {0:8} {1:25} {2:25} {3:6} {4:10} {5:10} {6}/{7}".format(
- "Host",
- "IF",
- "IP",
- "Proto",
- "MTU",
- "State",
- "Gate",
- "Def.Gate"
- )
- )
+
+ # main networks, target vars
+ _map = {}
# No matter of proto, at least one IP will be present for the network
+ # we interested in, since we are to make sure that L3 level
+ # is configured according to reclass model
for network in _reclass:
# shortcuts
_net = str(network)
- logger_cli.info("-> {}".format(_net))
+ _map[_net] = {}
if network not in _runtime:
# reclass has network that not found in runtime
self.errors.add_error(
@@ -290,6 +287,7 @@
# hostnames
names = sorted(_runtime[network].keys())
for hostname in names:
+ _notes = []
node = hostname.split('.')[0]
if not salt_master.is_node_available(hostname, log=False):
logger_cli.info(
@@ -300,9 +298,15 @@
self.errors.NET_NODE_NON_RESPONSIVE,
host=hostname
)
+ _notes.append(
+ self.errors.get_error_type_text(
+ self.errors.NET_NODE_NON_RESPONSIVE
+ )
+ )
continue
# lookup interface name on node using network CIDR
_if_name = _runtime[network][hostname][0]["name"]
+ _raw = self.interfaces[hostname][_if_name]['runtime']
# get proper reclass
_r = self.interfaces[hostname][_if_name]['reclass']
_if_name_suffix = ""
@@ -315,6 +319,11 @@
host=hostname,
if_name=_if_name
)
+ _notes.append(
+ self.errors.get_error_type_text(
+ self.errors.NET_NODE_UNEXPECTED_IF
+ )
+ )
_if_rc = "*"
if "proto" in _r:
@@ -379,6 +388,11 @@
ip=_ip_str,
gateway=_gate
)
+ _notes.append(
+ self.errors.get_error_type_text(
+ self.errors.NET_UNEXPECTED_GATEWAY
+ )
+ )
_gate_error = "*"
# IF status in reclass
@@ -389,6 +403,11 @@
host=hostname,
if_name=_if_name
)
+ _notes.append(
+ self.errors.get_error_type_text(
+ self.errors.NET_NO_RC_IF_STATUS
+ )
+ )
_up_error = "*"
_rc_mtu = _r['mtu'] if 'mtu' in _r else None
@@ -408,6 +427,11 @@
reclass_mtu=_rc_mtu,
runtime_mtu=_host['mtu']
)
+ _notes.append(
+ self.errors.get_error_type_text(
+ self.errors.NET_MTU_MISMATCH
+ )
+ )
_rc_mtu_s = "/" + _rc_mtu_s
_mtu_error = "*"
else:
@@ -424,48 +448,111 @@
if_cidr=_ip_str,
if_mtu=_host['mtu']
)
+ _notes.append(
+ self.errors.get_error_type_text(
+ self.errors.NET_MTU_EMPTY
+ )
+ )
_mtu_error = "*"
else:
# this is a VIP
_if_name = " "*7
_if_name_suffix = ""
_ip_str += " VIP"
- # Host IF IP Proto MTU State Gate Def.Gate
- _text = "{:7} {:17} {:25} {:6} {:10} " \
- "{:10} {} / {}".format(
- _if_name + _if_rc,
- _if_name_suffix,
- _ip_str,
- _proto,
- _host['mtu'] + _rc_mtu_s + _mtu_error,
- _host['state'] + _up_error,
- _gate + _gate_error,
- _d_gate_str
- )
- logger_cli.info(
- " {0:8} {1}".format(
- node,
- _text
+ # Save all data
+ _values = {
+ "interface": _if_name,
+ "interface_error": _if_rc,
+ "interface_note": _if_name_suffix,
+ "ip_address": _ip_str,
+ "address_type": _proto,
+ "rt_mtu": _host['mtu'],
+ "rc_mtu": _rc_mtu_s,
+ "mtu_error": _mtu_error,
+ "status": _host['state'],
+ "status_error": _up_error,
+ "subnet_gateway": _gate,
+ "subnet_gateway_error": _gate_error,
+ "default_gateway": _d_gate_str,
+ "raw_data": _raw,
+ "error_note": " and ".join(_notes)
+ }
+ if node in _map[_net]:
+ # add if to host
+ _map[_net][node].append(_values)
+ else:
+ _map[_net][node] = [_values]
+ _notes = []
+
+ # save map
+ self.map = _map
+ # other runtime networks found
+ # docker, etc
+
+ return
+
+ def print_map(self):
+ """
+ Create text report for CLI
+
+ :return: none
+ """
+ logger_cli.info("# Networks")
+ logger_cli.info(
+ " {0:8} {1:25} {2:25} {3:6} {4:10} {5:10} {6}/{7}".format(
+ "Host",
+ "IF",
+ "IP",
+ "Proto",
+ "MTU",
+ "State",
+ "Gate",
+ "Def.Gate"
+ )
+ )
+ for network in self.map.keys():
+ logger_cli.info("-> {}".format(network))
+ for hostname in self.map[network].keys():
+ node = hostname.split('.')[0]
+ _n = self.map[network][hostname]
+ for _i in _n:
+ # Host IF IP Proto MTU State Gate Def.Gate
+ _text = "{:7} {:17} {:25} {:6} {:10} " \
+ "{:10} {} / {}".format(
+ _i['interface'] + _i['interface_error'],
+ _i['interface_note'],
+ _i['ip_address'],
+ _i['address_type'],
+ _i['rt_mtu'] + _i['rc_mtu'] + _i['mtu_error'],
+ _i['status'] + _i['status_error'],
+ _i['subnet_gateway'] +
+ _i['subnet_gateway_error'],
+ _i['default_gateway']
)
- )
-
- logger_cli.info("\n# Other networks")
- _other = [n for n in _runtime if n not in _reclass]
- for network in _other:
- logger_cli.info("-> {}".format(str(network)))
- names = sorted(_runtime[network].keys())
-
- for hostname in names:
- for _n in _runtime[network][hostname]:
- _ifs = [str(ifs.ip) for ifs in _n['ifs']]
- _text = "{:25} {:25} {:6} {:10} {}".format(
- _n['name'],
- ", ".join(_ifs),
- "-",
- _n['mtu'],
- _n['state']
- )
logger_cli.info(
- " {0:8} {1}".format(hostname.split('.')[0], _text)
+ " {0:8} {1}".format(
+ node,
+ _text
+ )
)
- logger_cli.info("\n")
+
+ # logger_cli.info("\n# Other networks")
+ # _other = [n for n in _runtime if n not in _reclass]
+ # for network in _other:
+ # logger_cli.info("-> {}".format(str(network)))
+ # names = sorted(_runtime[network].keys())
+
+ # for hostname in names:
+ # for _n in _runtime[network][hostname]:
+ # _ifs = [str(ifs.ip) for ifs in _n['ifs']]
+ # _text = "{:25} {:25} {:6} {:10} {}".format(
+ # _n['name'],
+ # ", ".join(_ifs),
+ # "-",
+ # _n['mtu'],
+ # _n['state']
+ # )
+ # logger_cli.info(
+ # " {0:8} {1}".format(hostname.split('.')[0], _text)
+ # )
+ # logger_cli.info("\n")