Skip nodes functionality for Package and Network modules

Added to main entrypoint
- Skip nodes using simple argument with '*' as a trailing wildcard
- Skip nodes using file list

Usability improovement
- Node list preview in status line
- Node stats alignment in net report

Minor fixes:
- Python version detection (3.5+)
- Node counter for each status
- Proper node skip handling

Change-Id: I086ef501bc06f0e739df25349257f1c63a2e2fcf
Related-PROD: PROD-35009
diff --git a/cfg_checker/common/const.py b/cfg_checker/common/const.py
index 685c79a..3b17099 100644
--- a/cfg_checker/common/const.py
+++ b/cfg_checker/common/const.py
@@ -8,6 +8,7 @@
 _cnt = itertools.count()
 NODE_DOWN = next(_cnt)
 NODE_UP = next(_cnt)
+NODE_SKIP = next(_cnt)
 
 # version const order is important!
 # biggest get shown in report top row
@@ -42,12 +43,13 @@
     VERSION_DOWN: "downgraded",
     VERSION_WARN: "warning",
     VERSION_ERR: "error",
-    VERSION_NA: "no status"
+    VERSION_NA: "nostatus"
 }
 
 node_status = {
     NODE_UP: "up",
-    NODE_DOWN: "down"
+    NODE_DOWN: "down",
+    NODE_SKIP: "skip"
 }
 
 uknown_code = "unk"
diff --git a/cfg_checker/common/other.py b/cfg_checker/common/other.py
index a385b90..5a4c552 100644
--- a/cfg_checker/common/other.py
+++ b/cfg_checker/common/other.py
@@ -126,20 +126,20 @@
         else:
             raise ConfigException(_message)
 
-    def get_nodes_list(self, env, nodes_list):
+    def get_nodes_list(self, nodes_list, env_sting=None):
         _list = []
-        if env is None:
+        if env_sting is None:
             # nothing supplied, use the one in repo
             try:
                 if not nodes_list:
                     return []
-                with open(os.path.join(pkg_dir, nodes_list)) as _f:
+                with open(nodes_list) as _f:
                     _list.extend(_f.read().splitlines())
             except IOError as e:
                 raise ConfigException("# Error while loading file, '{}': "
                                       "{}".format(e.filename, e.strerror))
         else:
-            _list.extend(self.node_string_to_list(env))
+            _list.extend(self.node_string_to_list(env_sting))
 
         # validate names
         _invalid = []
@@ -151,7 +151,7 @@
             else:
                 _valid.append(_name)
 
-        return _valid
+        return _valid, _invalid
 
 
 utils = Utils()
diff --git a/cfg_checker/common/settings.py b/cfg_checker/common/settings.py
index 92c17a5..cca5142 100644
--- a/cfg_checker/common/settings.py
+++ b/cfg_checker/common/settings.py
@@ -1,4 +1,5 @@
 import os
+import sys
 
 from cfg_checker.common.exception import ConfigException
 
@@ -15,11 +16,17 @@
 
 
 class CheckerConfiguration(object):
+    @staticmethod
     def load_nodes_list():
-        return utils.get_nodes_list(
-            os.environ.get('CFG_ALL_NODES', None),
-            os.environ.get('SALT_NODE_LIST_FILE', None)
-        )
+        _file = os.environ.get('SALT_NODE_LIST_FILE', None)
+        if _file:
+            _v, _ = utils.get_nodes_list(
+                os.path.join(pkg_dir, _file),
+                env_sting=os.environ.get('CFG_ALL_NODES', None)
+            )
+            return _v
+        else:
+            return None
 
     def _init_values(self):
         """Load values from environment variables or put default ones
@@ -119,6 +126,16 @@
     def __init__(self):
         """Base configuration class. Only values that are common for all scripts
         """
+        # Make sure we running on Python 3
+        if sys.version_info[0] < 3 and sys.version_info[1] < 5:
+            logger_cli.error("# ERROR: Python 3.5+ is required")
+            sys.exit(1)
+        else:
+            logger_cli.debug("### Python version is {}.{}".format(
+                sys.version_info[0],
+                sys.version_info[1]
+            ))
+
         _env = os.getenv('SALT_ENV', None)
         self._init_env(_env)
         self._init_values()