From 77ffd6633718014c3ced954ac5c49e28d98f1b33 Mon Sep 17 00:00:00 2001
From: Helga Velroyen <helgav@google.com>
Date: Mon, 22 Oct 2012 11:19:48 +0200
Subject: [PATCH] Fix setting of 'failN1' flag for corner case

This patch includes:

* The 'failN1' flag is now only set if there is strictly less
  memory available than required for failover.
* Unit tests for that.

Signed-off-by: Helga Velroyen <helgav@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>
---
 htest/Test/Ganeti/HTools/Node.hs | 25 +++++++++++++++++++++++++
 htools/Ganeti/HTools/Node.hs     |  2 +-
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/htest/Test/Ganeti/HTools/Node.hs b/htest/Test/Ganeti/HTools/Node.hs
index 9631dd184..3e4ea8b32 100644
--- a/htest/Test/Ganeti/HTools/Node.hs
+++ b/htest/Test/Ganeti/HTools/Node.hs
@@ -120,6 +120,28 @@ prop_setMcpu node mc =
   Types.iPolicyVcpuRatio (Node.iPolicy newnode) ==? mc
     where newnode = Node.setMcpu node mc
 
+prop_setFmemGreater :: Node.Node -> Int -> Property
+prop_setFmemGreater node new_mem =
+  not (Node.failN1 node) && (Node.rMem node >= 0) &&
+  (new_mem > Node.rMem node) ==>
+  not (Node.failN1 (Node.setFmem node new_mem))
+
+prop_setFmemExact :: Node.Node -> Property
+prop_setFmemExact node =
+  not (Node.failN1 node) && (Node.rMem node >= 0) ==>
+  not (Node.failN1 (Node.setFmem node (Node.rMem node)))
+
+-- Check if adding an instance that consumes exactly all reserved
+-- memory does not raise an N+1 error
+prop_addPri_NoN1Fail :: Property
+prop_addPri_NoN1Fail =
+  forAll genOnlineNode $ \node ->
+  forAll (genInstanceSmallerThanNode node) $ \inst ->
+  let inst' = inst { Instance.mem = Node.fMem node - Node.rMem node }
+  in case Node.addPri node inst' of
+    Bad Types.FailN1 -> False
+    _ -> True
+
 -- | Check that an instance add with too high memory or disk will be
 -- rejected.
 prop_addPriFM :: Node.Node -> Instance.Instance -> Property
@@ -290,10 +312,13 @@ testSuite "HTools/Node"
             [ 'prop_setAlias
             , 'prop_setOffline
             , 'prop_setMcpu
+            , 'prop_setFmemGreater
+            , 'prop_setFmemExact
             , 'prop_setXmem
             , 'prop_addPriFM
             , 'prop_addPriFD
             , 'prop_addPriFC
+            , 'prop_addPri_NoN1Fail
             , 'prop_addSec
             , 'prop_addOfflinePri
             , 'prop_addOfflineSec
diff --git a/htools/Ganeti/HTools/Node.hs b/htools/Ganeti/HTools/Node.hs
index d6b98cbfb..72e533ed4 100644
--- a/htools/Ganeti/HTools/Node.hs
+++ b/htools/Ganeti/HTools/Node.hs
@@ -354,7 +354,7 @@ computePDsk used total = fromIntegral used / total
 -- | Sets the free memory.
 setFmem :: Node -> Int -> Node
 setFmem t new_mem =
-  let new_n1 = new_mem <= rMem t
+  let new_n1 = new_mem < rMem t
       new_mp = fromIntegral new_mem / tMem t
   in t { fMem = new_mem, failN1 = new_n1, pMem = new_mp }
 
-- 
GitLab