Reclass diff and list commands
diff --git a/cfg_checker/cfg_check.py b/cfg_checker/cfg_check.py
index a10d4a0..34a3102 100644
--- a/cfg_checker/cfg_check.py
+++ b/cfg_checker/cfg_check.py
@@ -1,15 +1,19 @@
 import argparse
 import os
+import reclass
 import sys
 import traceback
+
 from logging import INFO,  DEBUG
 
 import reporter
+
 from cfg_checker.common.exception import ConfigException
 from cfg_checker.common import utils, const
 from cfg_checker.common import config, logger, logger_cli, pkg_dir
 from cfg_checker.clients import salt
 
+import cfg_checker.reclass_cmp as reclass_cmp
 from cfg_checker.pkg_check import CloudPackageChecker
 from cfg_checker.network_checks import NetworkChecker
 
@@ -45,6 +49,39 @@
         raise ConfigException("No report filename supplied")
 
 
+def get_path_arg(path):
+    if os.path.exists(path):
+        return path
+    else:
+        raise ConfigException("'{}' not exists".format(path))
+
+
+def validate_model(path):
+    logger_cli.debug("\t...validating '{}' as a model".format(path))
+    _checks = []
+    _is_folder = os.path.isdir(path)
+    logger_cli.debug("\t- folder? -> {}".format(_is_folder))
+    _checks.append(_is_folder)
+    _has_classes = os.path.isdir(os.path.join(path, "classes"))
+    logger_cli.debug("\t- has classes? -> {}".format(_has_classes))
+    _checks.append(_has_classes)
+    _has_cluster = os.path.isdir(os.path.join(path, "classes", "cluster"))
+    logger_cli.debug("\t- has classes/cluster? -> {}".format(_has_cluster))
+    _checks.append(_has_cluster)
+    _has_system = os.path.isdir(os.path.join(path, "classes", "system"))
+    logger_cli.debug("\t- has classes/system? -> {}".format(_has_system))
+    _checks.append(_has_system)
+    _has_nodes = os.path.isdir(os.path.join(path, "nodes"))
+    logger_cli.debug("\t- has nodes? -> {}".format(_has_nodes))
+    _checks.append(_has_nodes)
+    
+    logger_cli.debug("\t-> {}".format(
+        all(_checks)
+    ))
+
+    return all(_checks)
+
+
 def packages_report(args):
     """Create package versions report
 
@@ -84,7 +121,29 @@
 
 
 def reclass_list(args):
-    logger_cli.info("Reclass list: to be implemented")
+    logger_cli.info("# Reclass list")
+    _path = get_path_arg(args.models_path)
+    
+    logger_cli.info("# ...models path is '{}'".format(args.models_path))
+    
+    models = {}
+    for _folder in os.listdir(args.models_path):
+        # validate item as a model
+        _model_path = os.path.join(
+            args.models_path,
+            _folder
+        )
+        _validated = validate_model(_model_path)
+        
+        if not _validated:
+            logger_cli.info("-> '{}' not a valid model".format(_folder))
+            continue
+        else:
+            models[_folder] = _model_path
+        
+        logger_cli.info("-> '{}' at '{}'".format(_folder, _model_path))
+        
+        # TODO: collect info about the model
 
     return
 
@@ -93,7 +152,38 @@
     logger_cli.info("Reclass comparer (HTML report: '{}'".format(args.file))
     _filename = get_file_arg(args)
 
-    return
+    # checking folder params
+    _model1 = get_path_arg(args.model1)
+    _model2 = get_path_arg(args.model2)
+    
+    # Do actual compare using hardcoded model names
+    mComparer = reclass_cmp.ModelComparer()
+
+    mComparer.model_name_1 = os.path.split(_model1)[1]
+    mComparer.model_path_1 = _model1
+    mComparer.model_name_2 = os.path.split(_model2)[1]
+    mComparer.model_path_2 = _model2
+    
+    mComparer.load_model_tree(
+        mComparer.model_name_1,
+        mComparer.model_path_1
+    )
+    mComparer.load_model_tree(
+        mComparer.model_name_2,
+        mComparer.model_path_2
+    )
+
+    diffs = mComparer.generate_model_report_tree()
+
+    report = reporter.ReportToFile(
+        reporter.HTMLModelCompare(),
+        _filename
+    )
+    logger_cli.info("# Generating report to {}".format(_filename))
+    report({
+        "nodes": {},
+        "diffs": diffs
+    })
 
 
 def config_check_entrypoint():
@@ -170,11 +260,28 @@
         'list',
         help="List models available to compare"
     )
+    reclass_list_parser.add_argument(
+        "-p",
+        "--models-path",
+        default="/srv/salt/",
+        help="Global path to search models in"
+    )
 
     reclass_diff_parser = reclass_subparsers.add_parser(
         'diff',
         help="List models available to compare"
     )
+    reclass_diff_parser.add_argument(
+        "--model1",
+        required=True,
+        help="Model A <path>. Model name is the folder name"
+    )
+    reclass_diff_parser.add_argument(
+        "--model2",
+        required=True,
+        help="Model B <path>. Model name is the folder name"
+    )
+
 
     #parse arguments
     try:
@@ -217,9 +324,12 @@
     try:
         config_check_entrypoint()
     except ConfigException as e:
+        logger_cli.error("\nERROR: {}".format(
+            e.message
+        ))
+
         exc_type, exc_value, exc_traceback = sys.exc_info()
-        logger_cli.error("\nERROR: {}\n\n{}".format(
-            e.message,
+        logger_cli.debug("\n{}".format(
             "".join(traceback.format_exception(
                 exc_type,
                 exc_value,