Try to prevent instance memory changes N+1 failures
authorIustin Pop <iustin@google.com>
Wed, 11 May 2011 15:54:27 +0000 (17:54 +0200)
committerIustin Pop <iustin@google.com>
Wed, 11 May 2011 16:14:20 +0000 (18:14 +0200)
There are multiple bugs with the code checking for N+1 failures in the
instance memory changes which needs significant changes, in the
meantime we can at least:

- change the warning message into an error (--force will skip checks)
- only make checks when we increase the memory

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>

NEWS
lib/cmdlib.py

diff --git a/NEWS b/NEWS
index 012baaf..73928ad 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -66,6 +66,9 @@ Many bug-fixes and a few new small features:
   instance's nodes)
 - Made the root_path and optional parameter for the xen-pvm hypervisor,
   to allow use of ``pvgrub`` as bootloader
+- Changed the instance memory modifications to only check out-of-memory
+  conditions on memory increases, and turned the secondary node warnings
+  into errors (they can still be overridden via ``--force``)
 
 And as usual, various improvements to the error messages, documentation
 and man pages.
index bcb9ccc..8b2374c 100644 (file)
@@ -9390,6 +9390,7 @@ class LUInstanceSetParams(LogicalUnit):
       self.be_inst = i_bedict # the new dict (without defaults)
     else:
       self.be_new = self.be_inst = {}
+    be_old = cluster.FillBE(instance)
 
     # osparams processing
     if self.op.osparams:
@@ -9401,7 +9402,8 @@ class LUInstanceSetParams(LogicalUnit):
 
     self.warn = []
 
-    if constants.BE_MEMORY in self.op.beparams and not self.op.force:
+    if (constants.BE_MEMORY in self.op.beparams and not self.op.force and
+        be_new[constants.BE_MEMORY] > be_old[constants.BE_MEMORY]):
       mem_check_list = [pnode]
       if be_new[constants.BE_AUTO_BALANCE]:
         # either we changed auto_balance to yes or it was from before
@@ -9442,16 +9444,17 @@ class LUInstanceSetParams(LogicalUnit):
         for node, nres in nodeinfo.items():
           if node not in instance.secondary_nodes:
             continue
-          msg = nres.fail_msg
-          if msg:
-            self.warn.append("Can't get info from secondary node %s: %s" %
-                             (node, msg))
-          elif not isinstance(nres.payload.get('memory_free', None), int):
-            self.warn.append("Secondary node %s didn't return free"
-                             " memory information" % node)
+          nres.Raise("Can't get info from secondary node %s" % node,
+                     prereq=True, ecode=errors.ECODE_STATE)
+          if not isinstance(nres.payload.get('memory_free', None), int):
+            raise errors.OpPrereqError("Secondary node %s didn't return free"
+                                       " memory information" % node,
+                                       errors.ECODE_STATE)
           elif be_new[constants.BE_MEMORY] > nres.payload['memory_free']:
-            self.warn.append("Not enough memory to failover instance to"
-                             " secondary node %s" % node)
+            raise errors.OpPrereqError("This change will prevent the instance"
+                                       " from failover to its secondary node"
+                                       " %s, due to not enough memory" % node,
+                                       errors.ECODE_STATE)
 
     # NIC processing
     self.nic_pnew = {}