From d10b27efb0e1b77e9a154cbdce39a4051c5be9db Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Mon, 9 Mar 2009 20:46:24 +0100
Subject: [PATCH] Change the node N+1 check model
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Currently, we fail a new instance placement if the new node status is
not N+1 compliant. This means that an allocation on an already N+1
failed node still fails, even though (conceptually) we're not worse than
before.

This patch changes this model to fail the allocation *only* if the node
was N+1 compliant before. This allows balancing to work on non-N+1 happy
clusters, with the caveat that they probably won't be N+1 happy at the
end.

Since we skip N+1 check in some cases, we add a new β€œfailHealth” check
that verifies the node still has strict positive free memory and disk
space.
---
 src/Node.hs | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/Node.hs b/src/Node.hs
index 7434dcab4..0312ccfd4 100644
--- a/src/Node.hs
+++ b/src/Node.hs
@@ -87,6 +87,10 @@ computeFailN1 :: Int -> Int -> Int -> Bool
 computeFailN1 new_rmem new_mem new_dsk =
     new_mem <= new_rmem || new_dsk <= 0
 
+-- | Given the new free memory and disk, fail if any of them is below zero.
+failHealth :: Int -> Int -> Bool
+failHealth new_mem new_dsk = new_mem <= 0 || new_dsk <= 0
+
 -- | Computes the maximum reserved memory for peers from a peer map.
 computeMaxRes :: PeerMap.PeerMap -> PeerMap.Elem
 computeMaxRes new_peers = PeerMap.maxElem new_peers
@@ -144,7 +148,7 @@ addPri t inst =
         new_mem = f_mem t - Instance.mem inst
         new_dsk = f_dsk t - Instance.dsk inst
         new_failn1 = computeFailN1 (maxRes t) new_mem new_dsk in
-      if new_failn1 then
+      if (failHealth new_mem new_dsk) || (new_failn1 && not (failN1 t)) then
         Nothing
       else
         let new_plist = iname:(plist t)
@@ -159,12 +163,13 @@ addSec :: Node -> Instance.Instance -> Int -> Maybe Node
 addSec t inst pdx =
     let iname = Instance.idx inst
         old_peers = peers t
+        old_mem = f_mem t
         new_dsk = f_dsk t - Instance.dsk inst
         new_peem = PeerMap.find pdx old_peers + Instance.mem inst
         new_peers = PeerMap.add pdx new_peem old_peers
         new_rmem = max (maxRes t) new_peem
-        new_failn1 = computeFailN1 new_rmem (f_mem t) new_dsk in
-    if new_failn1 then
+        new_failn1 = computeFailN1 new_rmem old_mem new_dsk in
+    if (failHealth old_mem new_dsk) || (new_failn1 && not (failN1 t)) then
         Nothing
     else
         let new_slist = iname:(slist t)
-- 
GitLab