From 784cd73790360e7172f9215d23d3edf59e5f8fce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Nussbaumer?= <rn@google.com>
Date: Fri, 25 Nov 2011 11:49:41 +0100
Subject: [PATCH] cmdlib: Adding _UpdateAndVerifySubDict helper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This helps with 2 dimensional dicts.
For example the hv_state and the disk_state dicts.

Signed-off-by: RenΓ© Nussbaumer <rn@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 lib/cmdlib.py                  | 20 +++++++++
 test/ganeti.cmdlib_unittest.py | 74 ++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)

diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 561a9bf6d..66ea5ae21 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -721,6 +721,26 @@ def _GetUpdatedParams(old_params, update_dict,
   return params_copy
 
 
+def _UpdateAndVerifySubDict(base, updates, type_check):
+  """Updates and verifies a dict with sub dicts of the same type.
+
+  @param base: The dict with the old data
+  @param updates: The dict with the new data
+  @param type_check: Dict suitable to ForceDictType to verify correct types
+  @returns: A new dict with updated and verified values
+
+  """
+  def fn(old, value):
+    new = _GetUpdatedParams(old, value)
+    utils.ForceDictType(new, type_check)
+    return new
+
+  ret = copy.deepcopy(base)
+  ret.update(dict((key, fn(base.get(key, {}), value))
+                  for key, value in updates.items()))
+  return ret
+
+
 def _ReleaseLocks(lu, level, names=None, keep=None):
   """Releases locks owned by an LU.
 
diff --git a/test/ganeti.cmdlib_unittest.py b/test/ganeti.cmdlib_unittest.py
index e69faf3d6..c8be6d65f 100755
--- a/test/ganeti.cmdlib_unittest.py
+++ b/test/ganeti.cmdlib_unittest.py
@@ -447,5 +447,79 @@ class TestLoadNodeEvacResult(unittest.TestCase):
     self.assertFalse(lu.warning_log)
 
 
+class TestUpdateAndVerifySubDict(unittest.TestCase):
+  def setUp(self):
+    self.type_check = {
+        "a": constants.VTYPE_INT,
+        "b": constants.VTYPE_STRING,
+        "c": constants.VTYPE_BOOL,
+        "d": constants.VTYPE_STRING,
+        }
+
+  def test(self):
+    old_test = {
+      "foo": {
+        "d": "blubb",
+        "a": 321,
+        },
+      "baz": {
+        "a": 678,
+        "b": "678",
+        "c": True,
+        },
+      }
+    test = {
+      "foo": {
+        "a": 123,
+        "b": "123",
+        "c": True,
+        },
+      "bar": {
+        "a": 321,
+        "b": "321",
+        "c": False,
+        },
+      }
+
+    mv = {
+      "foo": {
+        "a": 123,
+        "b": "123",
+        "c": True,
+        "d": "blubb"
+        },
+      "bar": {
+        "a": 321,
+        "b": "321",
+        "c": False,
+        },
+      "baz": {
+        "a": 678,
+        "b": "678",
+        "c": True,
+        },
+      }
+
+    verified = cmdlib._UpdateAndVerifySubDict(old_test, test, self.type_check)
+    self.assertEqual(verified, mv)
+
+  def testWrong(self):
+    test = {
+      "foo": {
+        "a": "blubb",
+        "b": "123",
+        "c": True,
+        },
+      "bar": {
+        "a": 321,
+        "b": "321",
+        "c": False,
+        },
+      }
+
+    self.assertRaises(errors.TypeEnforcementError,
+                      cmdlib._UpdateAndVerifySubDict, {}, test, self.type_check)
+
+
 if __name__ == "__main__":
   testutils.GanetiTestProgram()
-- 
GitLab