Change fromObj error messages
[ganeti-local] / Ganeti / HTools / Node.hs
index 1216f1c..ffdad4e 100644 (file)
@@ -33,7 +33,7 @@ module Ganeti.HTools.Node
     -- ** Finalization after data loading
     , buildPeers
     , setIdx
-    , setName
+    , setAlias
     , setOffline
     , setXmem
     , setFmem
@@ -41,6 +41,10 @@ module Ganeti.HTools.Node
     , setSec
     , setMdsk
     , setMcpu
+    -- * Tag maps
+    , addTags
+    , delTags
+    , rejectAddTags
     -- * Instance (re)location
     , removePri
     , removeSec
@@ -48,6 +52,9 @@ module Ganeti.HTools.Node
     , addSec
     -- * Stats
     , availDisk
+    , availMem
+    , availCpu
+    , conflictingPrimaries
     -- * Formatting
     , defaultFields
     , showHeader
@@ -55,11 +62,13 @@ module Ganeti.HTools.Node
     , list
     -- * Misc stuff
     , AssocList
+    , AllocElement
     , noSecondary
     ) where
 
 import Data.List
 import qualified Data.Map as Map
+import qualified Data.Foldable as Foldable
 import Text.Printf (printf)
 
 import qualified Ganeti.HTools.Container as Container
@@ -76,6 +85,7 @@ type TagMap = Map.Map String Int
 -- | The node type.
 data Node = Node
     { name     :: String    -- ^ The node name
+    , alias    :: String    -- ^ The shortened name (for display purposes)
     , tMem     :: Double    -- ^ Total memory (MiB)
     , nMem     :: Int       -- ^ Node memory (MiB)
     , fMem     :: Int       -- ^ Free memory (MiB)
@@ -112,8 +122,9 @@ data Node = Node
 instance T.Element Node where
     nameOf = name
     idxOf = idx
-    setName = setName
+    setAlias = setAlias
     setIdx = setIdx
+    allNames n = [name n, alias n]
 
 -- | A simple name for the int, node association list.
 type AssocList = [(T.Ndx, Node)]
@@ -121,18 +132,14 @@ type AssocList = [(T.Ndx, Node)]
 -- | A simple name for a node map.
 type List = Container.Container Node
 
+-- | A simple name for an allocation element (here just for logistic
+-- reasons)
+type AllocElement = (List, Instance.Instance, [Node])
+
 -- | Constant node index for a non-moveable instance.
 noSecondary :: T.Ndx
 noSecondary = -1
 
--- | No limit value
-noLimit :: Double
-noLimit = -1
-
--- | No limit int value
-noLimitInt :: Int
-noLimitInt = -1
-
 -- * Helper functions
 
 -- | Add a tag to a tagmap
@@ -156,7 +163,15 @@ delTags = foldl' delTag
 
 -- | Check if we can add a list of tags to a tagmap
 rejectAddTags :: TagMap -> [String] -> Bool
-rejectAddTags t = any (flip Map.member t)
+rejectAddTags t = any (`Map.member` t)
+
+-- | Check how many primary instances have conflicting tags. The
+-- algorithm to compute this is to sum the count of all tags, then
+-- subtract the size of the tag map (since each tag has at least one,
+-- non-conflicting instance); this is equivalent to summing the
+-- values in the tag map minus one.
+conflictingPrimaries :: Node -> Int
+conflictingPrimaries (Node { pTags = t }) = Foldable.sum t - Map.size t
 
 -- * Initialization functions
 
@@ -168,7 +183,8 @@ create :: String -> Double -> Int -> Int -> Double
        -> Int -> Double -> Bool -> Node
 create name_init mem_t_init mem_n_init mem_f_init
        dsk_t_init dsk_f_init cpu_t_init offline_init =
-    Node { name  = name_init
+    Node { name = name_init
+         , alias = name_init
          , tMem = mem_t_init
          , nMem = mem_n_init
          , fMem = mem_f_init
@@ -188,26 +204,34 @@ create name_init mem_t_init mem_n_init mem_f_init
          , pCpu = 0
          , offline = offline_init
          , xMem = 0
-         , mDsk = noLimit
-         , mCpu = noLimit
-         , loDsk = noLimitInt
-         , hiCpu = noLimitInt
+         , mDsk = T.defReservedDiskRatio
+         , mCpu = T.defVcpuRatio
+         , loDsk = mDskToloDsk T.defReservedDiskRatio dsk_t_init
+         , hiCpu = mCpuTohiCpu T.defVcpuRatio cpu_t_init
          , utilPool = T.baseUtil
          , utilLoad = T.zeroUtil
          , pTags = Map.empty
          }
 
+-- | Conversion formula from mDsk\/tDsk to loDsk
+mDskToloDsk :: Double -> Double -> Int
+mDskToloDsk mval tdsk = floor (mval * tdsk)
+
+-- | Conversion formula from mCpu\/tCpu to hiCpu
+mCpuTohiCpu :: Double -> Double -> Int
+mCpuTohiCpu mval tcpu = floor (mval * tcpu)
+
 -- | Changes the index.
 --
 -- This is used only during the building of the data structures.
 setIdx :: Node -> T.Ndx -> Node
 setIdx t i = t {idx = i}
 
--- | Changes the name.
+-- | Changes the alias.
 --
 -- This is used only during the building of the data structures.
-setName :: Node -> String -> Node
-setName t s = t {name = s}
+setAlias :: Node -> String -> Node
+setAlias t s = t { alias = s }
 
 -- | Sets the offline attribute.
 setOffline :: Node -> Bool -> Node
@@ -219,14 +243,11 @@ setXmem t val = t { xMem = val }
 
 -- | Sets the max disk usage ratio
 setMdsk :: Node -> Double -> Node
-setMdsk t val = t { mDsk = val,
-                    loDsk = if val == noLimit
-                             then noLimitInt
-                             else floor (val * tDsk t) }
+setMdsk t val = t { mDsk = val, loDsk = mDskToloDsk val (tDsk t) }
 
 -- | Sets the max cpu usage ratio
 setMcpu :: Node -> Double -> Node
-setMcpu t val = t { mCpu = val, hiCpu = floor (val * tCpu t) }
+setMcpu t val = t { mCpu = val, hiCpu = mCpuTohiCpu val (tCpu t) }
 
 -- | Computes the maximum reserved memory for peers from a peer map.
 computeMaxRes :: P.PeerMap -> P.Elem
@@ -330,20 +351,21 @@ addPri t inst =
         new_load = utilLoad t `T.addUtil` Instance.util inst
         inst_tags = Instance.tags inst
         old_tags = pTags t
-    in if new_mem <= 0 then T.OpFail T.FailMem
-       else if new_dsk <= 0 || mDsk t > new_dp then T.OpFail T.FailDisk
-       else if new_failn1 && not (failN1 t) then T.OpFail T.FailMem
-       else if l_cpu >= 0 && l_cpu < new_pcpu then T.OpFail T.FailCPU
-       else if rejectAddTags old_tags inst_tags
-            then T.OpFail T.FailTags
-       else
-           let new_plist = iname:pList t
-               new_mp = fromIntegral new_mem / tMem t
-               r = t { pList = new_plist, fMem = new_mem, fDsk = new_dsk
-                     , failN1 = new_failn1, pMem = new_mp, pDsk = new_dp
-                     , uCpu = new_ucpu, pCpu = new_pcpu, utilLoad = new_load
-                     , pTags = addTags old_tags inst_tags }
-           in T.OpGood r
+    in case () of
+         _ | new_mem <= 0 -> T.OpFail T.FailMem
+           | new_dsk <= 0 || mDsk t > new_dp -> T.OpFail T.FailDisk
+           | new_failn1 && not (failN1 t) -> T.OpFail T.FailMem
+           | l_cpu >= 0 && l_cpu < new_pcpu -> T.OpFail T.FailCPU
+           | rejectAddTags old_tags inst_tags -> T.OpFail T.FailTags
+           | otherwise ->
+               let new_plist = iname:pList t
+                   new_mp = fromIntegral new_mem / tMem t
+                   r = t { pList = new_plist, fMem = new_mem, fDsk = new_dsk
+                         , failN1 = new_failn1, pMem = new_mp, pDsk = new_dp
+                         , uCpu = new_ucpu, pCpu = new_pcpu
+                         , utilLoad = new_load
+                         , pTags = addTags old_tags inst_tags }
+               in T.OpGood r
 
 -- | Adds a secondary instance.
 addSec :: Node -> Instance.Instance -> T.Ndx -> T.OpResult Node
@@ -361,14 +383,17 @@ addSec t inst pdx =
         old_load = utilLoad t
         new_load = old_load { T.dskWeight = T.dskWeight old_load +
                                             T.dskWeight (Instance.util inst) }
-    in if new_dsk <= 0 || mDsk t > new_dp then T.OpFail T.FailDisk
-       else if new_failn1 && not (failN1 t) then T.OpFail T.FailMem
-       else let new_slist = iname:sList t
-                r = t { sList = new_slist, fDsk = new_dsk
-                      , peers = new_peers, failN1 = new_failn1
-                      , rMem = new_rmem, pDsk = new_dp
-                      , pRem = new_prem, utilLoad = new_load }
-            in T.OpGood r
+    in case () of
+         _ | new_dsk <= 0 || mDsk t > new_dp -> T.OpFail T.FailDisk
+           | Instance.mem inst >= old_mem -> T.OpFail T.FailMem
+           | new_failn1 && not (failN1 t) -> T.OpFail T.FailMem
+           | otherwise ->
+               let new_slist = iname:sList t
+                   r = t { sList = new_slist, fDsk = new_dsk
+                         , peers = new_peers, failN1 = new_failn1
+                         , rMem = new_rmem, pDsk = new_dp
+                         , pRem = new_prem, utilLoad = new_load }
+               in T.OpGood r
 
 -- * Stats functions
 
@@ -377,19 +402,35 @@ availDisk :: Node -> Int
 availDisk t =
     let _f = fDsk t
         _l = loDsk t
-    in
-      if _l == noLimitInt
-      then _f
-      else if _f < _l
-           then 0
-           else _f - _l
+    in if _f < _l
+       then 0
+       else _f - _l
+
+-- | Computes the amount of available memory on a given node
+availMem :: Node -> Int
+availMem t =
+    let _f = fMem t
+        _l = rMem t
+    in if _f < _l
+       then 0
+       else _f - _l
+
+-- | Computes the amount of available memory on a given node
+availCpu :: Node -> Int
+availCpu t =
+    let _u = uCpu t
+        _l = hiCpu t
+    in if _l >= _u
+       then _l - _u
+       else 0
 
 -- * Display functions
 
 showField :: Node -> String -> String
 showField t field =
     case field of
-      "name" -> name t
+      "name" -> alias t
+      "fqdn" -> name t
       "status" -> if offline t then "-"
                   else if failN1 t then "*" else " "
       "tmem" -> printf "%5.0f" $ tMem t
@@ -414,7 +455,7 @@ showField t field =
       "nload" -> printf "%5.3f" uN
       "ptags" -> intercalate "," . map (\(k, v) -> printf "%s=%d" k v) .
                  Map.toList $ pTags t
-      _ -> printf "<unknown field>"
+      _ -> T.unknownField
     where
       T.DynUtil { T.cpuWeight = uC, T.memWeight = uM,
                   T.dskWeight = uD, T.netWeight = uN } = utilLoad t
@@ -425,6 +466,7 @@ showHeader :: String -> (String, Bool)
 showHeader field =
     case field of
       "name" -> ("Name", False)
+      "fqdn" -> ("Name", False)
       "status" -> ("F", False)
       "tmem" -> ("t_mem", True)
       "nmem" -> ("n_mem", True)
@@ -447,7 +489,7 @@ showHeader field =
       "dload" -> ("lDsk", True)
       "nload" -> ("lNet", True)
       "ptags" -> ("PrimaryTags", False)
-      _ -> ("<unknown field>", False)
+      _ -> (T.unknownField, False)
 
 -- | String converter for the node list functionality.
 list :: [String] -> Node -> [String]