htools: change behaviour for offline instances
authorAgata Murawska <agatamurawska@google.com>
Tue, 15 Nov 2011 10:28:40 +0000 (11:28 +0100)
committerAgata Murawska <agatamurawska@google.com>
Wed, 16 Nov 2011 13:16:30 +0000 (14:16 +0100)
Signed-off-by: Agata Murawska <agatamurawska@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>

htools/Ganeti/HTools/Instance.hs
htools/Ganeti/HTools/Loader.hs
htools/Ganeti/HTools/Node.hs
htools/Ganeti/HTools/QC.hs
htools/Ganeti/HTools/Utils.hs

index 1d7bc78..22d3c96 100644 (file)
@@ -32,6 +32,9 @@ module Ganeti.HTools.Instance
     , List
     , create
     , instanceRunning
+    , instanceOffline
+    , instanceDown
+    , applyIfOnline
     , setIdx
     , setName
     , setAlias
@@ -52,6 +55,8 @@ import qualified Ganeti.HTools.Types as T
 import qualified Ganeti.HTools.Container as Container
 import qualified Ganeti.Constants as C
 
+import Ganeti.HTools.Utils
+
 -- * Type declarations
 
 -- | The instance type.
@@ -85,6 +90,22 @@ instanceRunning (Instance {runSt = T.Running}) = True
 instanceRunning (Instance {runSt = T.ErrorUp}) = True
 instanceRunning _                               = False
 
+-- | Check if instance is offline.
+instanceOffline :: Instance -> Bool
+instanceOffline (Instance {runSt = T.AdminOffline}) = True
+instanceOffline _                                    = False
+
+-- | Check if instance is down.
+instanceDown :: Instance -> Bool
+instanceDown inst | instanceRunning inst = False
+instanceDown inst | instanceOffline inst = False
+instanceDown _                           = True
+
+-- | Apply the function if the instance is online. Otherwise use
+-- the initial value
+applyIfOnline :: Instance -> (a -> a) -> a -> a
+applyIfOnline = applyIf . not . instanceOffline
+
 -- | Constant holding the local storage templates.
 --
 -- /Note:/ Currently Ganeti only exports node total/free disk space
index 9bbad6e..0e5f10a 100644 (file)
@@ -306,7 +306,7 @@ checkData nl il =
         (\ msgs node ->
              let nname = Node.name node
                  nilst = map (`Container.find` il) (Node.pList node)
-                 dilst = filter (not . Instance.instanceRunning) nilst
+                 dilst = filter Instance.instanceDown nilst
                  adj_mem = sum . map Instance.mem $ dilst
                  delta_mem = truncate (Node.tMem node)
                              - Node.nMem node
@@ -329,8 +329,10 @@ checkData nl il =
 nodeImem :: Node.Node -> Instance.List -> Int
 nodeImem node il =
     let rfind = flip Container.find il
-    in sum . map (Instance.mem . rfind)
-           $ Node.pList node
+        il' = map rfind $ Node.pList node
+        oil' = filter (not . Instance.instanceOffline) il'
+    in sum . map Instance.mem $ oil'
+
 
 -- | Compute the amount of disk used by instances on a node (either primary
 -- or secondary).
index 5ebfbd7..c2116d4 100644 (file)
@@ -310,12 +310,13 @@ removePri :: Node -> Instance.Instance -> Node
 removePri t inst =
     let iname = Instance.idx inst
         new_plist = delete iname (pList t)
-        new_mem = fMem t + Instance.mem inst
+        new_mem = Instance.applyIfOnline inst (+ Instance.mem inst) (fMem t)
         new_dsk = fDsk t + Instance.dsk inst
         new_mp = fromIntegral new_mem / tMem t
         new_dp = fromIntegral new_dsk / tDsk t
         new_failn1 = new_mem <= rMem t
-        new_ucpu = uCpu t - Instance.vcpus inst
+        new_ucpu = Instance.applyIfOnline inst
+                   (\x -> x - Instance.vcpus inst) (uCpu t)
         new_rcpu = fromIntegral new_ucpu / tCpu t
         new_load = utilLoad t `T.subUtil` Instance.util inst
     in t { pList = new_plist, fMem = new_mem, fDsk = new_dsk
@@ -374,12 +375,13 @@ addPriEx force t inst =
     let iname = Instance.idx inst
         uses_disk = Instance.usesLocalStorage inst
         cur_dsk = fDsk t
-        new_mem = fMem t - Instance.mem inst
+        new_mem = Instance.applyIfOnline inst
+                  (\x -> x - Instance.mem inst) (fMem t)
         new_dsk = if uses_disk
                   then cur_dsk - Instance.dsk inst
                   else cur_dsk
         new_failn1 = new_mem <= rMem t
-        new_ucpu = uCpu t + Instance.vcpus inst
+        new_ucpu = Instance.applyIfOnline inst (+ Instance.vcpus inst) (uCpu t)
         new_pcpu = fromIntegral new_ucpu / tCpu t
         new_dp = fromIntegral new_dsk / tDsk t
         l_cpu = mCpu t
@@ -415,7 +417,8 @@ addSecEx force t inst pdx =
         old_peers = peers t
         old_mem = fMem t
         new_dsk = fDsk t - Instance.dsk inst
-        secondary_needed_mem = if Instance.autoBalance inst
+        secondary_needed_mem = if Instance.autoBalance inst &&
+                                  not (Instance.instanceOffline inst)
                                then Instance.mem inst
                                else 0
         new_peem = P.find pdx old_peers + secondary_needed_mem
index a55ba02..a03830e 100644 (file)
@@ -695,7 +695,8 @@ prop_Node_setMcpu node mc =
 -- | Check that an instance add with too high memory or disk will be
 -- rejected.
 prop_Node_addPriFM node inst = Instance.mem inst >= Node.fMem node &&
-                               not (Node.failN1 node)
+                               not (Node.failN1 node) &&
+                               not (Instance.instanceOffline inst)
                                ==>
                                case Node.addPri node inst'' of
                                  Types.OpFail Types.FailMem -> True
@@ -715,7 +716,8 @@ prop_Node_addPriFD node inst = Instance.dsk inst >= Node.fDsk node &&
           inst'' = inst' { Instance.dsk = Instance.dsk inst }
 
 prop_Node_addPriFC node inst (Positive extra) =
-    not (Node.failN1 node) ==>
+    not (Node.failN1 node) &&
+    not (Instance.instanceOffline inst) ==>
         case Node.addPri node inst'' of
           Types.OpFail Types.FailCPU -> True
           _ -> False
@@ -726,14 +728,34 @@ prop_Node_addPriFC node inst (Positive extra) =
 -- | Check that an instance add with too high memory or disk will be
 -- rejected.
 prop_Node_addSec node inst pdx =
-    (Instance.mem inst >= (Node.fMem node - Node.rMem node) ||
+    ((Instance.mem inst >= (Node.fMem node - Node.rMem node) &&
+      not (Instance.instanceOffline inst)) ||
      Instance.dsk inst >= Node.fDsk node) &&
     not (Node.failN1 node)
     ==> isFailure (Node.addSec node inst pdx)
         where _types = (node::Node.Node, inst::Instance.Instance, pdx::Int)
 
+-- | Check that an offline instance with reasonable disk size can always
+-- be added.
+prop_Node_addPriOffline node =
+    forAll (arbitrary `suchThat`
+            (\ x ->  (Instance.dsk x  < Node.fDsk node) &&
+                      Instance.instanceOffline x)) $ \inst ->
+    case Node.addPri node inst of
+      Types.OpGood _ -> True
+      _ -> False
+
+prop_Node_addSecOffline node pdx =
+    forAll (arbitrary `suchThat`
+            (\ x ->  (Instance.dsk x  < Node.fDsk node) &&
+                      Instance.instanceOffline x)) $ \inst ->
+    case Node.addSec node inst pdx of
+      Types.OpGood _ -> True
+      _ -> False
+
 -- | Checks for memory reservation changes.
 prop_Node_rMem inst =
+    not (Instance.instanceOffline inst) ==>
     forAll (arbitrary `suchThat` ((> Types.unitMem) . Node.fMem)) $ \node ->
     -- ab = auto_balance, nb = non-auto_balance
     -- we use -1 as the primary node of the instance
@@ -808,6 +830,8 @@ testSuite "Node"
               , 'prop_Node_addPriFD
               , 'prop_Node_addPriFC
               , 'prop_Node_addSec
+              , 'prop_Node_addPriOffline
+              , 'prop_Node_addSecOffline
               , 'prop_Node_rMem
               , 'prop_Node_setMdsk
               , 'prop_Node_tagMaps_idempotent
index 43f9330..4b0dd4a 100644 (file)
@@ -30,6 +30,7 @@ module Ganeti.HTools.Utils
     , stdDev
     , if'
     , select
+    , applyIf
     , commaJoin
     , readEitherString
     , JSRecord
@@ -76,6 +77,10 @@ debugXy = seq . debug
 
 -- * Miscellaneous
 
+-- | Apply the function if condition holds, otherwise use default value.
+applyIf :: Bool -> (a -> a) -> a -> a
+applyIf b f x = if b then f x else x
+
 -- | Comma-join a string list.
 commaJoin :: [String] -> String
 commaJoin = intercalate ","