Migrating to Python v3

 - support for Python v3.8.x
 - support for Python v3.5.x
 - new tag, 2019.2.8
 - updates class generation and iterators
 - unittests updated with coverage >75%
 - new coverage routines
 - unittests profiling
 - full fake data for unittests
 - unittest testrun is ~1.5 seconds long

Bugfixes
 - 34834, proper use of 'sudo' option
 - multiple proper iterator use
 - 37919, show warning when installed and candidate versions
   are newer comparing to release version

Change-Id: Idd6b889f7ce94ae0c832e2f0a0346e4fdc3264a3
Related-PROD: PROD-34834 PROD-34664 PROD-34919
diff --git a/cfg_checker/common/__init__.py b/cfg_checker/common/__init__.py
index 8316e39..752373f 100644
--- a/cfg_checker/common/__init__.py
+++ b/cfg_checker/common/__init__.py
@@ -1,10 +1,8 @@
-import const
+from cfg_checker.common.log import logger, logger_cli
 
-from log import logger, logger_cli
+from cfg_checker.common.other import Utils
 
-from other import Utils
-
-from settings import config
+from cfg_checker.common.settings import config
 
 
 def nested_set(_d, _keys, _value):
@@ -18,7 +16,6 @@
 
 
 utils = Utils()
-const = const
 logger = logger
 logger_cli = logger_cli
 config = config
diff --git a/cfg_checker/common/config_file.py b/cfg_checker/common/config_file.py
index 87f4759..c70e5a6 100644
--- a/cfg_checker/common/config_file.py
+++ b/cfg_checker/common/config_file.py
@@ -1,7 +1,7 @@
 import configparser
 import os
 
-from cfg_checker.common import logger_cli
+from . import logger_cli
 
 
 class ConfigFile(object):
diff --git a/cfg_checker/common/const.py b/cfg_checker/common/const.py
index 9e5fea2..685c79a 100644
--- a/cfg_checker/common/const.py
+++ b/cfg_checker/common/const.py
@@ -75,7 +75,7 @@
     "unk": "uknown"
 }
 
-ubuntu_releases = ["trusty", "xenial", "ubuntu"]
+ubuntu_releases = ["trusty", "xenial", "ubuntu", "bionic"]
 all_arch = ["amd64"]
 repo_types = {
     "main": "Officially supported software",
diff --git a/cfg_checker/common/exception.py b/cfg_checker/common/exception.py
index 52aab2d..2536099 100644
--- a/cfg_checker/common/exception.py
+++ b/cfg_checker/common/exception.py
@@ -1,5 +1,3 @@
-from exceptions import Exception
-
 
 class CheckerBaseExceptions(Exception):
     pass
diff --git a/cfg_checker/common/file_utils.py b/cfg_checker/common/file_utils.py
index c550184..398ea66 100644
--- a/cfg_checker/common/file_utils.py
+++ b/cfg_checker/common/file_utils.py
@@ -67,7 +67,7 @@
 
     _dict = {
         'fd': fd.fileno(),
-        'mode': oct(mode & 0777),
+        'mode': oct(mode & 0o777),
         'device': hex(dev),
         'inode': ino,
         'hard_links': nlink,
@@ -102,3 +102,11 @@
         return "... folder '{}' created".format(_folder)
     else:
         return "... folder is at '{}'".format(_folder)
+
+
+def ensure_folder_removed(_folder):
+    if os.path.exists(_folder):
+        os.rmdir(_folder)
+        return "... folder '{}' removed".format(_folder)
+    else:
+        return "... folder '{}' not exists".format(_folder)
diff --git a/cfg_checker/common/salt_utils.py b/cfg_checker/common/salt_utils.py
index 7bd6ce7..dd6fbec 100644
--- a/cfg_checker/common/salt_utils.py
+++ b/cfg_checker/common/salt_utils.py
@@ -5,15 +5,15 @@
 import os
 import time
 
+import requests
+
 from cfg_checker.common import config, logger, logger_cli
 from cfg_checker.common.exception import InvalidReturnException, SaltException
 from cfg_checker.common.other import shell
 
-import requests
-
 
 def _extract_password(_raw):
-    if not isinstance(_raw, unicode):
+    if not isinstance(_raw, str):
         raise InvalidReturnException(_raw)
     else:
         try:
@@ -69,10 +69,14 @@
 
     :return: password string
     """
-    _cmd = "salt-call"
-    _args = "--out=json pillar.get _param:salt_api_password"
+    _cmd = []
+    if config.ssh_uses_sudo:
+        _cmd = ["sudo"]
+    # salt commands
+    _cmd.append("salt-call")
+    _cmd.append("--out=json pillar.get _param:salt_api_password")
     try:
-        _result = shell(" ".join([_cmd, _args]))
+        _result = shell(" ".join(_cmd))
     except OSError as e:
         raise SaltException(
             "Salt error calling '{}': '{}'\n"
@@ -386,7 +390,7 @@
             param=path,
             kwarg=_kwarg
         )
-        return salt_output[salt_output.keys()[0]]
+        return [*salt_output.values()][0]
 
     def f_append_master(self, path, strings_list, makedirs=True):
         _kwarg = {
@@ -400,7 +404,7 @@
             param=_args,
             kwarg=_kwarg
         )
-        return salt_output[salt_output.keys()[0]]
+        return [*salt_output.values()][0]
 
     def mkdir(self, target, path, tgt_type=None):
         salt_output = self.cmd(
@@ -452,7 +456,7 @@
             param=_arg,
             kwarg=_kwarg
         )
-        return salt_output[salt_output.keys()[0]]
+        return [*salt_output.values()][0]
 
     def cache_file(self, target, source_path):
         salt_output = self.cmd(
@@ -460,7 +464,7 @@
             "cp.cache_file",
             param=source_path
         )
-        return salt_output[salt_output.keys()[0]]
+        return [*salt_output.values()][0]
 
     def get_file(self, target, source_path, target_path, tgt_type=None):
         return self.cmd(
diff --git a/cfg_checker/common/settings.py b/cfg_checker/common/settings.py
index 33e7c25..92c17a5 100644
--- a/cfg_checker/common/settings.py
+++ b/cfg_checker/common/settings.py
@@ -1,10 +1,10 @@
 import os
 
-from exception import ConfigException
+from cfg_checker.common.exception import ConfigException
 
-from log import logger_cli
+from cfg_checker.common.log import logger_cli
 
-from other import utils
+from cfg_checker.common.other import utils
 
 pkg_dir = os.path.dirname(__file__)
 pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir)