Update merge_settings script to support removing interfaces

Currently there is provision to override default settings using
.override files. But there is no way to remove a certain interface
exported by settings daemon. Example: This will be useful for PowerCap
interface. Power Cap is hardcoded toa specific object_path in dcmi. So
if there is a Service which also exports PowerCap interface it can
remove that interface from settings daemon.

Signed-off-by: Gaurav Gandhi <gauravgandhi@google.com>
Change-Id: Ib27bdc3cf205957de5893bb9373727e2bbc9c036
diff --git a/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager/merge_settings.py b/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager/merge_settings.py
index d910da5..68c2437 100755
--- a/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager/merge_settings.py
+++ b/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager/merge_settings.py
@@ -5,34 +5,40 @@
 Override files are processed in the order given.
 
 Usage:
-    merge_settings.py <target yaml> [override yamls]
+    merge_settings.py <target yaml> [override/remove yamls]
 """
 import sys
 import yaml
 import copy
 
-def dict_merge(target, source):
+def dict_merge(target, source, remove):
     """Deep merge for dicts.
 
-    Works like dict.update() that recursively updates any dict values present in
-    both parameters.
+    Works like dict.update() that recursively updates/removes any dict values
+    present in both parameters.
 
     Args:
         target (dict): Values to be overwritten by corresponding values from
             `source`.
         source (dict): Overriding values. Not changed by call.
+        remove (bool): If this is true then it removes the entry provided in
+            'source' along with all entries under it from 'target'. Otherwise
+            it overrides the values from 'source'
 
     Returns:
-        `target` with values overwritten from those in `source` at any and all
-        levels of nested dicts.
+        `target` with values overwritten/removed from those in `source` at any 
+        and all levels of nested dicts.
     """
     if not isinstance(source, dict):
         return source
     for k, v in source.items():
         if k in target and isinstance(target[k], dict):
-            dict_merge(target[k], v)
+            dict_merge(target[k], v, remove)
         else:
-            target[k] = copy.deepcopy(v)
+            if remove is True:
+                target.pop(k)
+            else:
+                target[k] = copy.deepcopy(v)
     return target
 
 if len(sys.argv) < 2:
@@ -48,10 +54,16 @@
     print('Loaded target YAML file ' + target_filename)
 
 for override_filename in sys.argv[2:]:
-    with open(override_filename) as override_file:
-        override = yaml.safe_load(override_file)
-        dict_merge(data, override)
-        print('Merged override YAML file ' + override_filename)
+    if override_filename.endswith('.override.yml'):
+        with open(override_filename) as override_file:
+            override = yaml.safe_load(override_file)
+            dict_merge(data, override, False)
+            print('Merged override YAML file ' + override_filename)
+    elif override_filename.endswith('.remove.yml'):
+        with open(override_filename) as override_file:
+            override = yaml.safe_load(override_file)
+            dict_merge(data, override, True)
+            print('Removed data from source YAML file' + override_filename)
 
 with open(target_filename, 'w') as target_file:
     yaml.dump(data, target_file)
diff --git a/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager_git.bb b/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager_git.bb
index 175e735..e3e7245 100644
--- a/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager_git.bb
+++ b/meta-phosphor/recipes-phosphor/settings/phosphor-settings-manager_git.bb
@@ -36,8 +36,8 @@
              SETTINGS_YAML=${STAGING_DIR_NATIVE}${settings_datadir}/defaults.yaml \
              "
 
-# Collect files in SRC_URI that end in ".override.yml" and call a script that
-# writes their contents over that of settings.yaml, which is then updated to
+# Collect files in SRC_URI that end in ".override.yml" or ".remove.yml" and call a script that
+# writes/removes their contents from that of settings.yaml, which is then updated to
 # the merged data values.
 # This doesn't correctly handle globs in ".override.yml" entries in SRC_URI.
 python do_merge_settings () {
@@ -58,7 +58,7 @@
         cmd.append(os.path.join(settingsdir, 'mrw-settings.override.yaml'))
 
     fetch = bb.fetch2.Fetch([], d)
-    override_urls = [url for url in fetch.urls if url.endswith('.override.yml')]
+    override_urls = [url for url in fetch.urls if url.endswith(('.override.yml', '.remove.yml'))]
     for url in override_urls:
         bb.debug(2, 'Overriding with source: ' + url)
         local_base = os.path.basename(fetch.localpath(url))