The masterd.instance is mocked out and checked that the correct
TransferInstanceData call is placed.

Signed-off-by: Aaron Karper <[email protected]>
---
 Makefile.am                                   |  1 +
 test/py/cmdlib/instance_unittest.py           | 15 +++++++
 test/py/cmdlib/testsupport/cmdlib_testcase.py | 13 ++++++
 test/py/cmdlib/testsupport/masterd_mock.py    | 59 +++++++++++++++++++++++++++
 4 files changed, 88 insertions(+)
 create mode 100644 test/py/cmdlib/testsupport/masterd_mock.py

diff --git a/Makefile.am b/Makefile.am
index f662831..117e1f3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1763,6 +1763,7 @@ python_test_support = \
        test/py/cmdlib/testsupport/config_mock.py \
        test/py/cmdlib/testsupport/iallocator_mock.py \
        test/py/cmdlib/testsupport/livelock_mock.py \
+       test/py/cmdlib/testsupport/masterd_mock.py \
        test/py/cmdlib/testsupport/netutils_mock.py \
        test/py/cmdlib/testsupport/processor_mock.py \
        test/py/cmdlib/testsupport/rpc_runner_mock.py \
diff --git a/test/py/cmdlib/instance_unittest.py 
b/test/py/cmdlib/instance_unittest.py
index 4406be9..084fef2 100644
--- a/test/py/cmdlib/instance_unittest.py
+++ b/test/py/cmdlib/instance_unittest.py
@@ -1594,9 +1594,24 @@ class TestLUInstanceMove(CmdlibTestCase):
         .CreateSuccessfulNodeResult(self.node, "")
 
     inst = self.cfg.AddNewInstance(admin_state=constants.ADMINST_UP)
+    old_node = inst.primary_node
     op = opcodes.OpInstanceMove(instance_name=inst.name,
                                 target_node=self.node.name)
     self.ExecOpCode(op)
+    self.masterd_mod.instance.TransferInstanceData.assert_called_with(
+        mock.ANY, mock.ANY, old_node, self.node.uuid, self.node.secondary_ip,
+        mock.ANY, inst, [mock.ANY])
+
+  def testMoveInstanceNoCopy(self):
+    self.masterd.instance.TransferInstanceData.return_value = [True]
+    inst = self.cfg.AddNewInstance(disk_template=constants.DT_SHARED_FILE)
+    old_node = inst.primary_node
+    op = opcodes.OpInstanceMove(instance_name=inst.name,
+                                target_node=self.node.name)
+    self.ExecOpCode(op)
+    self.masterd_mod.instance.TransferInstanceData.assert_called_with(
+        mock.ANY, mock.ANY, old_node, self.node.uuid, self.node.secondary_ip,
+        mock.ANY, inst, [])
 
   def testMoveFailingStartInstance(self):
     self.rpc.call_node_info.return_value = \
diff --git a/test/py/cmdlib/testsupport/cmdlib_testcase.py 
b/test/py/cmdlib/testsupport/cmdlib_testcase.py
index f245f45..1472779 100644
--- a/test/py/cmdlib/testsupport/cmdlib_testcase.py
+++ b/test/py/cmdlib/testsupport/cmdlib_testcase.py
@@ -39,6 +39,7 @@ import traceback
 from cmdlib.testsupport.config_mock import ConfigMock
 from cmdlib.testsupport.iallocator_mock import patchIAllocator
 from cmdlib.testsupport.livelock_mock import LiveLockMock
+from cmdlib.testsupport.masterd_mock import patchMasterd, CreateMasterdMock
 from cmdlib.testsupport.netutils_mock import patchNetutils, \
   SetupDefaultNetutilsMock
 from cmdlib.testsupport.processor_mock import ProcessorMock
@@ -136,6 +137,7 @@ class CmdlibTestCase(testutils.GanetiTestCase):
     self._netutils_patcher = None
     self._ssh_patcher = None
     self._rpc_patcher = None
+    self._masterd_patcher = None
 
     try:
       runtime.InitArchInfo()
@@ -158,6 +160,9 @@ class CmdlibTestCase(testutils.GanetiTestCase):
     if self._rpc_patcher is not None:
       self._rpc_patcher.stop()
       self._rpc_patcher = None
+    if self._masterd_patcher is not None:
+      self._masterd_patcher.stop()
+      self._masterd_patcher = None
 
   def tearDown(self):
     super(CmdlibTestCase, self).tearDown()
@@ -183,6 +188,7 @@ class CmdlibTestCase(testutils.GanetiTestCase):
     self.rpc = CreateRpcRunnerMock()
     self.ctx = GanetiContextMock(self)
     self.mcpu = ProcessorMock(self.ctx)
+    self.masterd = CreateMasterdMock()
 
     self._StopPatchers()
     try:
@@ -215,6 +221,13 @@ class CmdlibTestCase(testutils.GanetiTestCase):
       # this test module does not use rpc, no patching performed
       self._rpc_patcher = None
 
+    try:
+      self._masterd_patcher = patchMasterd(self._GetTestModule())
+      self.masterd_mod = self._masterd_patcher.start()
+    except (ImportError, AttributeError):
+      # this test module does not use masterd, no patching performed
+      self._masterd_patcher = None
+
   def GetMockLU(self):
     """Creates a mock L{LogialUnit} with access to the mocked config etc.
 
diff --git a/test/py/cmdlib/testsupport/masterd_mock.py 
b/test/py/cmdlib/testsupport/masterd_mock.py
new file mode 100644
index 0000000..59ba8f5
--- /dev/null
+++ b/test/py/cmdlib/testsupport/masterd_mock.py
@@ -0,0 +1,59 @@
+#
+#
+
+# Copyright (C) 2014 Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Support for mocking the Masterd"""
+
+
+import mock
+
+from ganeti import masterd
+
+from cmdlib.testsupport.util import patchModule
+
+
+# pylint: disable=C0103
+def patchMasterd(module_under_test):
+  """Patches the L{ganeti.masterd} module for tests.
+
+  This function is meant to be used as a decorator for test methods.
+
+  @type module_under_test: string
+  @param module_under_test: the module within cmdlib which is tested. The
+        "ganeti.cmdlib" prefix is optional.
+
+  """
+  return patchModule(module_under_test, "masterd", wraps=masterd)
+
+
+def CreateMasterdMock():
+  """Creates a new L{mock.MagicMock} tailored for the L{masterd} module.
+
+  """
+  return mock.MagicMock(spec=masterd)
-- 
2.1.0.rc2.206.gedb03e5

Reply via email to