Packages report updates

- All Errors are warnings by default
- If package version differs across nodes
  warning becomes error

Change-Id: I1e6d338cfae252cc5d8ee6ededdd757ec070eb2c
Related-PROD: PROD-38972
diff --git a/cfg_checker/common/const.py b/cfg_checker/common/const.py
index 5826f43..9e5fea2 100644
--- a/cfg_checker/common/const.py
+++ b/cfg_checker/common/const.py
@@ -15,6 +15,7 @@
 VERSION_OK = next(_cnt)
 VERSION_UP = next(_cnt)
 VERSION_DOWN = next(_cnt)
+VERSION_WARN = next(_cnt)
 VERSION_ERR = next(_cnt)
 
 # action const order is important!
@@ -39,6 +40,7 @@
     VERSION_OK: "ok",
     VERSION_UP: "upgraded",
     VERSION_DOWN: "downgraded",
+    VERSION_WARN: "warning",
     VERSION_ERR: "error",
     VERSION_NA: "no status"
 }
@@ -65,6 +67,8 @@
     "mon": "monitoring",
     "msg": "messaging",
     "mtr": "stacklight_metering",
+    "ntw": "contrail_networking",
+    "nal": "contrail_analytics",
     "osd": "storage_node",
     "prx": "proxy",
     "rgw": "storage_rados",
diff --git a/cfg_checker/common/other.py b/cfg_checker/common/other.py
index 2620d05..c5ad7c8 100644
--- a/cfg_checker/common/other.py
+++ b/cfg_checker/common/other.py
@@ -20,6 +20,35 @@
     return _ps
 
 
+def merge_dict(source, destination):
+    """
+    Dict merger, thanks to vincent
+    http://stackoverflow.com/questions/20656135/python-deep-merge-dictionary-data
+
+    >>> a = { 'first' : { 'all_rows' : { 'pass' : 'dog', 'number' : '1' } } }
+    >>> b = { 'first' : { 'all_rows' : { 'fail' : 'cat', 'number' : '5' } } }
+    >>> merge(b, a) == {
+        'first': {
+            'all_rows': {
+                'pass': 'dog',
+                'fail': 'cat',
+                'number': '5'
+            }
+        }
+    }
+    True
+    """
+    for key, value in source.items():
+        if isinstance(value, dict):
+            # get node or create one
+            node = destination.setdefault(key, {})
+            merge_dict(value, node)
+        else:
+            destination[key] = value
+
+    return destination
+
+
 class Utils(object):
     @staticmethod
     def validate_name(fqdn, message=False):