diff --git a/ansible/action_plugins/merge_configs.py b/ansible/action_plugins/merge_configs.py
index 7218a2ac9970be40ba533b0b5595701840af1830..27fcc532324cdffb4d956142add5402f9672dbe4 100644
--- a/ansible/action_plugins/merge_configs.py
+++ b/ansible/action_plugins/merge_configs.py
@@ -1,6 +1,7 @@
 #!/usr/bin/python
 
 # Copyright 2015 Sam Yaple
+# Copyright 2017 99Cloud Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -14,12 +15,71 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import ConfigParser
+
+import collections
 import inspect
 import os
-from six import StringIO
 
 from ansible.plugins import action
+from six import StringIO
+
+from oslo_config import iniparser
+
+
+class OverrideConfigParser(iniparser.BaseParser):
+
+    def __init__(self):
+        self._cur_sections = collections.OrderedDict()
+        self._sections = collections.OrderedDict()
+        self._cur_section = None
+
+    def assignment(self, key, value):
+        cur_value = self._cur_section.get(key)
+        if len(value) == 1 and value[0] == '':
+            value = []
+        if not cur_value:
+            self._cur_section[key] = [value]
+        else:
+            self._cur_section[key].append(value)
+
+    def parse(self, lineiter):
+        self._cur_sections = collections.OrderedDict()
+        super(OverrideConfigParser, self).parse(lineiter)
+
+        # merge _cur_sections into _sections
+        for section, values in self._cur_sections.items():
+            if section not in self._sections:
+                self._sections[section] = collections.OrderedDict()
+            for key, value in values.items():
+                self._sections[section][key] = value
+
+    def new_section(self, section):
+        cur_section = self._cur_sections.get(section)
+        if not cur_section:
+            cur_section = collections.OrderedDict()
+            self._cur_sections[section] = cur_section
+        self._cur_section = cur_section
+        return cur_section
+
+    def write(self, fp):
+        def write_key_value(key, values):
+            for v in values:
+                if not v:
+                    fp.write('{} =\n'.format(key))
+                for index, value in enumerate(v):
+                    if index == 0:
+                        fp.write('{} = {}\n'.format(key, value))
+                    else:
+                        fp.write('{}   {}\n'.format(len(key)*' ', value))
+
+        def write_section(section):
+            for key, values in section.items():
+                write_key_value(key, values)
+
+        for section in self._sections:
+            fp.write('[{}]\n'.format(section))
+            write_section(self._sections[section])
+            fp.write('\n')
 
 
 class ActionModule(action.ActionBase):
@@ -33,7 +93,7 @@ class ActionModule(action.ActionBase):
                 template_data = f.read()
             result = self._templar.template(template_data)
             fakefile = StringIO(result)
-            config.readfp(fakefile)
+            config.parse(fakefile)
             fakefile.close()
 
     def run(self, tmp=None, task_vars=None):
@@ -62,7 +122,7 @@ class ActionModule(action.ActionBase):
         temp_vars = task_vars.copy()
         temp_vars.update(extra_vars)
 
-        config = ConfigParser.ConfigParser()
+        config = OverrideConfigParser()
         old_vars = self._templar._available_variables
         self._templar.set_available_variables(temp_vars)
 
diff --git a/tests/test_merge_config.py b/tests/test_merge_config.py
new file mode 100644
index 0000000000000000000000000000000000000000..2300308cf1414e5e6ca83c8437376682e722d224
--- /dev/null
+++ b/tests/test_merge_config.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python
+
+# Copyright 2016 99cloud Inc.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import imp
+import os
+import sys
+
+import mock
+from oslotest import base
+from six import StringIO
+
+
+PROJECT_DIR = os.path.abspath(os.path.join(os. path.dirname(__file__), '../'))
+MERGE_CONFIG_FILE = os.path.join(PROJECT_DIR,
+                                 'ansible/action_plugins/merge_configs.py')
+
+sys.modules['ansible.plugins'] = mock.MagicMock()
+
+merge_configs = imp.load_source('merge_configs', MERGE_CONFIG_FILE)
+
+TESTA = '''[DEFAULT]
+key1 = b
+       c
+key2 = v1
+       v2
+key3 = v3
+key3 = v4
+key4 = v5
+
+[b]
+b_key1 = 1
+b_key2 = 1
+         2
+
+[c]
+c_key1 =
+c_key2 = 1 2 3
+         4 5 6
+
+'''
+
+TESTB = '''[DEFAULT]
+key2 = v3
+       v4
+       v5
+key4 = v4
+key4 =
+
+[b]
+b_key2 = 2
+
+'''
+
+# TESTC is TESTA + TESTB
+TESTC = '''[DEFAULT]
+key1 = b
+       c
+key2 = v3
+       v4
+       v5
+key3 = v3
+key3 = v4
+key4 = v4
+key4 =
+
+[b]
+b_key1 = 1
+b_key2 = 2
+
+[c]
+c_key1 =
+c_key2 = 1 2 3
+         4 5 6
+
+'''
+
+
+class OverrideConfigParserTest(base.BaseTestCase):
+
+    def test_read_write(self):
+        for ini in [TESTA, TESTB, TESTC]:
+            parser = merge_configs.OverrideConfigParser()
+            parser.parse(StringIO(ini))
+            output = StringIO()
+            parser.write(output)
+            self.assertEqual(ini, output.getvalue())
+
+    def test_merge(self):
+        parser = merge_configs.OverrideConfigParser()
+        parser.parse(StringIO(TESTA))
+        parser.parse(StringIO(TESTB))
+        output = StringIO()
+        parser.write(output)
+        self.assertEqual(TESTC, output.getvalue())