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/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):