Move part of the loader pipeline to ClusterData
[ganeti-local] / Ganeti / HTools / Node.hs
index cdb375d..73162e6 100644 (file)
@@ -6,7 +6,7 @@
 
 {-
 
-Copyright (C) 2009 Google Inc.
+Copyright (C) 2009, 2010 Google Inc.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -66,11 +66,13 @@ module Ganeti.HTools.Node
     , AssocList
     , AllocElement
     , noSecondary
+    , computeGroups
     ) where
 
-import Data.List
+import Data.List hiding (group)
 import qualified Data.Map as Map
 import qualified Data.Foldable as Foldable
+import Data.Ord (comparing)
 import Text.Printf (printf)
 
 import qualified Ganeti.HTools.Container as Container
@@ -119,7 +121,8 @@ data Node = Node
     , utilPool :: T.DynUtil -- ^ Total utilisation capacity
     , utilLoad :: T.DynUtil -- ^ Sum of instance utilisation
     , pTags    :: TagMap    -- ^ Map of primary instance tags and their count
-    } deriving (Show)
+    , group    :: T.Gdx     -- ^ The node's group (index)
+    } deriving (Show, Eq)
 
 instance T.Element Node where
     nameOf = name
@@ -136,7 +139,7 @@ type List = Container.Container Node
 
 -- | A simple name for an allocation element (here just for logistic
 -- reasons)
-type AllocElement = (List, Instance.Instance, [Node])
+type AllocElement = (List, Instance.Instance, [Node], T.Score)
 
 -- | Constant node index for a non-moveable instance.
 noSecondary :: T.Ndx
@@ -182,9 +185,9 @@ conflictingPrimaries (Node { pTags = t }) = Foldable.sum t - Map.size t
 -- The index and the peers maps are empty, and will be need to be
 -- update later via the 'setIdx' and 'buildPeers' functions.
 create :: String -> Double -> Int -> Int -> Double
-       -> Int -> Double -> Bool -> Node
+       -> Int -> Double -> Bool -> T.Gdx -> Node
 create name_init mem_t_init mem_n_init mem_f_init
-       dsk_t_init dsk_f_init cpu_t_init offline_init =
+       dsk_t_init dsk_f_init cpu_t_init offline_init group_init =
     Node { name = name_init
          , alias = name_init
          , tMem = mem_t_init
@@ -213,6 +216,7 @@ create name_init mem_t_init mem_n_init mem_f_init
          , utilPool = T.baseUtil
          , utilLoad = T.zeroUtil
          , pTags = Map.empty
+         , group = group_init
          }
 
 -- | Conversion formula from mDsk\/tDsk to loDsk
@@ -409,7 +413,7 @@ addSecEx force t inst pdx =
     in case () of
          _ | new_dsk <= 0 -> T.OpFail T.FailDisk
            | mDsk t > new_dp && strict -> T.OpFail T.FailDisk
-           | Instance.mem inst >= old_mem -> T.OpFail T.FailMem
+           | Instance.mem inst >= old_mem && strict -> T.OpFail T.FailMem
            | new_failn1 && not (failN1 t) && strict -> T.OpFail T.FailMem
            | otherwise ->
                let new_slist = iname:sList t
@@ -521,6 +525,7 @@ showHeader field =
       "nload" -> ("lNet", True)
       "ptags" -> ("PrimaryTags", False)
       "peermap" -> ("PeerMap", False)
+      -- TODO: add node fields (group.uuid, group)
       _ -> (T.unknownField, False)
 
 -- | String converter for the node list functionality.
@@ -534,3 +539,11 @@ defaultFields =
     , "rmem", "tdsk", "fdsk", "tcpu", "ucpu", "pcnt", "scnt"
     , "pfmem", "pfdsk", "rcpu"
     , "cload", "mload", "dload", "nload" ]
+
+-- | Split a list of nodes into a list of (node group UUID, list of
+-- associated nodes)
+computeGroups :: [Node] -> [(T.Gdx, [Node])]
+computeGroups nodes =
+  let nodes' = sortBy (comparing group) nodes
+      nodes'' = groupBy (\a b -> group a == group b) nodes'
+  in map (\nl -> (group (head nl), nl)) nodes''