More code reorganizations
[ganeti-local] / Ganeti / HTools / Cluster.hs
index 0d14d15..33d523c 100644 (file)
@@ -15,6 +15,7 @@ module Ganeti.HTools.Cluster
     , Solution(..)
     , Table(..)
     , Removal
     , Solution(..)
     , Table(..)
     , Removal
+    , Score
     -- * Generic functions
     , totalResources
     -- * First phase functions
     -- * Generic functions
     , totalResources
     -- * First phase functions
@@ -31,7 +32,6 @@ module Ganeti.HTools.Cluster
     , compCV
     , printStats
     -- * Loading functions
     , compCV
     , printStats
     -- * Loading functions
-    , loadData
     , checkData
     ) where
 
     , checkData
     ) where
 
@@ -39,16 +39,14 @@ import Data.List
 import Data.Maybe (isNothing, fromJust)
 import Text.Printf (printf)
 import Data.Function
 import Data.Maybe (isNothing, fromJust)
 import Text.Printf (printf)
 import Data.Function
+import Control.Monad
 
 import qualified Ganeti.HTools.Container as Container
 import qualified Ganeti.HTools.Instance as Instance
 import qualified Ganeti.HTools.Node as Node
 
 import qualified Ganeti.HTools.Container as Container
 import qualified Ganeti.HTools.Instance as Instance
 import qualified Ganeti.HTools.Node as Node
+import Ganeti.HTools.Types
 import Ganeti.HTools.Utils
 
 import Ganeti.HTools.Utils
 
-type NodeList = Container.Container Node.Node
-type InstanceList = Container.Container Instance.Instance
--- | The type used to hold idx-to-name mappings
-type NameList = [(Int, String)]
 -- | A separate name for the cluster score type
 type Score = Double
 
 -- | A separate name for the cluster score type
 type Score = Double
 
@@ -202,7 +200,7 @@ those nodes.
 computeBadItems :: NodeList -> InstanceList ->
                    ([Node.Node], [Instance.Instance])
 computeBadItems nl il =
 computeBadItems :: NodeList -> InstanceList ->
                    ([Node.Node], [Instance.Instance])
 computeBadItems nl il =
-  let bad_nodes = verifyN1 $ Container.elems nl
+  let bad_nodes = verifyN1 $ filter (not . Node.offline) $ Container.elems nl
       bad_instances = map (\idx -> Container.find idx il) $
                       sort $ nub $ concat $
                       map (\ n -> (Node.slist n) ++ (Node.plist n)) bad_nodes
       bad_instances = map (\idx -> Container.find idx il) $
                       sort $ nub $ concat $
                       map (\ n -> (Node.slist n) ++ (Node.plist n)) bad_nodes
@@ -343,11 +341,10 @@ applyMove nl inst Failover =
         old_s = Container.find old_sdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
         old_s = Container.find old_sdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
-        new_p = Node.addPri int_s inst
-        new_s = Node.addSec int_p inst old_sdx
-        new_nl = if isNothing(new_p) || isNothing(new_s) then Nothing
-                 else Just $ Container.addTwo old_pdx (fromJust new_s)
-                      old_sdx (fromJust new_p) nl
+        new_nl = do -- Maybe monad
+          new_p <- Node.addPri int_s inst
+          new_s <- Node.addSec int_p inst old_sdx
+          return $ Container.addTwo old_pdx new_s old_sdx new_p nl
     in (new_nl, Instance.setBoth inst old_sdx old_pdx, old_sdx, old_pdx)
 
 -- Replace the primary (f:, r:np, f)
     in (new_nl, Instance.setBoth inst old_sdx old_pdx, old_sdx, old_pdx)
 
 -- Replace the primary (f:, r:np, f)
@@ -359,12 +356,11 @@ applyMove nl inst (ReplacePrimary new_pdx) =
         tgt_n = Container.find new_pdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
         tgt_n = Container.find new_pdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
-        new_p = Node.addPri tgt_n inst
-        new_s = Node.addSec int_s inst new_pdx
-        new_nl = if isNothing(new_p) || isNothing(new_s) then Nothing
-                 else Just $ Container.add new_pdx (fromJust new_p) $
-                      Container.addTwo old_pdx int_p
-                               old_sdx (fromJust new_s) nl
+        new_nl = do -- Maybe monad
+          new_p <- Node.addPri tgt_n inst
+          new_s <- Node.addSec int_s inst new_pdx
+          return $ Container.add new_pdx new_p $
+                 Container.addTwo old_pdx int_p old_sdx new_s nl
     in (new_nl, Instance.setPri inst new_pdx, new_pdx, old_sdx)
 
 -- Replace the secondary (r:ns)
     in (new_nl, Instance.setPri inst new_pdx, new_pdx, old_sdx)
 
 -- Replace the secondary (r:ns)
@@ -374,10 +370,9 @@ applyMove nl inst (ReplaceSecondary new_sdx) =
         old_s = Container.find old_sdx nl
         tgt_n = Container.find new_sdx nl
         int_s = Node.removeSec old_s inst
         old_s = Container.find old_sdx nl
         tgt_n = Container.find new_sdx nl
         int_s = Node.removeSec old_s inst
-        new_s = Node.addSec tgt_n inst old_pdx
-        new_nl = if isNothing(new_s) then Nothing
-                 else Just $ Container.addTwo new_sdx (fromJust new_s)
-                      old_sdx int_s nl
+        new_nl = Node.addSec tgt_n inst old_pdx >>=
+                 \new_s -> return $ Container.addTwo new_sdx
+                           new_s old_sdx int_s nl
     in (new_nl, Instance.setSec inst new_sdx, old_pdx, new_sdx)
 
 -- Replace the secondary and failover (r:np, f)
     in (new_nl, Instance.setSec inst new_sdx, old_pdx, new_sdx)
 
 -- Replace the secondary and failover (r:np, f)
@@ -389,12 +384,11 @@ applyMove nl inst (ReplaceAndFailover new_pdx) =
         tgt_n = Container.find new_pdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
         tgt_n = Container.find new_pdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
-        new_p = Node.addPri tgt_n inst
-        new_s = Node.addSec int_p inst new_pdx
-        new_nl = if isNothing(new_p) || isNothing(new_s) then Nothing
-                 else Just $ Container.add new_pdx (fromJust new_p) $
-                      Container.addTwo old_pdx (fromJust new_s)
-                               old_sdx int_s nl
+        new_nl = do -- Maybe monad
+          new_p <- Node.addPri tgt_n inst
+          new_s <- Node.addSec int_p inst new_pdx
+          return $ Container.add new_pdx new_p $
+                 Container.addTwo old_pdx new_s old_sdx int_s nl
     in (new_nl, Instance.setBoth inst new_pdx old_pdx, new_pdx, old_pdx)
 
 -- Failver and replace the secondary (f, r:ns)
     in (new_nl, Instance.setBoth inst new_pdx old_pdx, new_pdx, old_pdx)
 
 -- Failver and replace the secondary (f, r:ns)
@@ -406,12 +400,11 @@ applyMove nl inst (FailoverAndReplace new_sdx) =
         tgt_n = Container.find new_sdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
         tgt_n = Container.find new_sdx nl
         int_p = Node.removePri old_p inst
         int_s = Node.removeSec old_s inst
-        new_p = Node.addPri int_s inst
-        new_s = Node.addSec tgt_n inst old_sdx
-        new_nl = if isNothing(new_p) || isNothing(new_s) then Nothing
-                 else Just $ Container.add new_sdx (fromJust new_s) $
-                      Container.addTwo old_sdx (fromJust new_p)
-                               old_pdx int_p nl
+        new_nl = do -- Maybe monad
+          new_p <- Node.addPri int_s inst
+          new_s <- Node.addSec tgt_n inst old_sdx
+          return $ Container.add new_sdx new_s $
+                 Container.addTwo old_sdx new_p old_pdx int_p nl
     in (new_nl, Instance.setBoth inst old_sdx new_sdx, old_sdx, new_sdx)
 
 checkSingleStep :: Table -- ^ The original table
     in (new_nl, Instance.setBoth inst old_sdx new_sdx, old_sdx, new_sdx)
 
 checkSingleStep :: Table -- ^ The original table
@@ -478,8 +471,10 @@ checkMove nodes_idx ini_tbl victims =
         -- iterate over all instances, computing the best move
         best_tbl =
             foldl'
         -- iterate over all instances, computing the best move
         best_tbl =
             foldl'
-            (\ step_tbl elem -> compareTables step_tbl $
-                                checkInstanceMove nodes_idx ini_tbl elem)
+            (\ step_tbl elem ->
+                 if Instance.snode elem == Node.noSecondary then step_tbl
+                    else compareTables step_tbl $
+                         checkInstanceMove nodes_idx ini_tbl elem)
             ini_tbl victims
         Table _ _ _ best_plc = best_tbl
     in
             ini_tbl victims
         Table _ _ _ best_plc = best_tbl
     in
@@ -691,98 +686,6 @@ printStats nl =
 
 -- Loading functions
 
 
 -- Loading functions
 
-{- | Convert newline and delimiter-separated text.
-
-This function converts a text in tabular format as generated by
-@gnt-instance list@ and @gnt-node list@ to a list of objects using a
-supplied conversion function.
-
--}
-loadTabular :: String -> ([String] -> (String, a))
-            -> (a -> Int -> a) -> ([(String, Int)], [(Int, a)])
-loadTabular text_data convert_fn set_fn =
-    let lines_data = lines text_data
-        rows = map (sepSplit '|') lines_data
-        kerows = (map convert_fn rows)
-        idxrows = map (\ (idx, (k, v)) -> ((k, idx), (idx, set_fn v idx)))
-                  (zip [0..] kerows)
-    in unzip idxrows
-
--- | For each instance, add its index to its primary and secondary nodes
-fixNodes :: [(Int, Node.Node)]
-         -> [(Int, Instance.Instance)]
-         -> [(Int, Node.Node)]
-fixNodes nl il =
-    foldl' (\accu (idx, inst) ->
-                let
-                    assocEqual = (\ (i, _) (j, _) -> i == j)
-                    pdx = Instance.pnode inst
-                    sdx = Instance.snode inst
-                    pold = fromJust $ lookup pdx accu
-                    sold = fromJust $ lookup sdx accu
-                    pnew = Node.setPri pold idx
-                    snew = Node.setSec sold idx
-                    ac1 = deleteBy assocEqual (pdx, pold) accu
-                    ac2 = deleteBy assocEqual (sdx, sold) ac1
-                    ac3 = (pdx, pnew):(sdx, snew):ac2
-                in ac3) nl il
-
--- | Compute the longest common suffix of a NameList list that
--- | starts with a dot
-longestDomain :: NameList -> String
-longestDomain [] = ""
-longestDomain ((_,x):xs) =
-    let
-        onlyStrings = snd $ unzip xs
-    in
-      foldr (\ suffix accu -> if all (isSuffixOf suffix) onlyStrings
-                              then suffix
-                              else accu)
-      "" $ filter (isPrefixOf ".") (tails x)
-
--- | Remove tails from the (Int, String) lists
-stripSuffix :: String -> NameList -> NameList
-stripSuffix suffix lst =
-    let sflen = length suffix in
-    map (\ (key, name) -> (key, take ((length name) - sflen) name)) lst
-
-{-| Initializer function that loads the data from a node and list file
-    and massages it into the correct format. -}
-loadData :: String -- ^ Node data in text format
-         -> String -- ^ Instance data in text format
-         -> (Container.Container Node.Node,
-             Container.Container Instance.Instance,
-             String, NameList, NameList)
-loadData ndata idata =
-    let
-    {- node file: name t_mem n_mem f_mem t_disk f_disk -}
-        (ktn, nl) = loadTabular ndata
-                    (\ (name:tm:nm:fm:td:fd:[]) ->
-                         (name,
-                          Node.create (read tm) (read nm)
-                                  (read fm) (read td) (read fd)))
-                    Node.setIdx
-    {- instance file: name mem disk status pnode snode -}
-        (kti, il) = loadTabular idata
-                    (\ (name:mem:dsk:status:pnode:snode:[]) ->
-                         (name,
-                          Instance.create (read mem) (read dsk)
-                              status
-                              (fromJust $ lookup pnode ktn)
-                              (fromJust $ lookup snode ktn)))
-                    Instance.setIdx
-        nl2 = fixNodes nl il
-        il3 = Container.fromAssocList il
-        nl3 = Container.fromAssocList
-             (map (\ (k, v) -> (k, Node.buildPeers v il3 (length nl2))) nl2)
-        xtn = swapPairs ktn
-        xti = swapPairs kti
-        common_suffix = longestDomain (xti ++ xtn)
-        stn = stripSuffix common_suffix xtn
-        sti = stripSuffix common_suffix xti
-    in
-      (nl3, il3, common_suffix, stn, sti)
-
 -- | Compute the amount of memory used by primary instances on a node.
 nodeImem :: Node.Node -> InstanceList -> Int
 nodeImem node il =
 -- | Compute the amount of memory used by primary instances on a node.
 nodeImem :: Node.Node -> InstanceList -> Int
 nodeImem node il =
@@ -798,7 +701,6 @@ nodeIdsk node il =
     in sum . map Instance.dsk .
        map rfind $ (Node.plist node) ++ (Node.slist node)
 
     in sum . map Instance.dsk .
        map rfind $ (Node.plist node) ++ (Node.slist node)
 
-
 -- | Check cluster data for consistency
 checkData :: NodeList -> InstanceList -> NameList -> NameList
           -> ([String], NodeList)
 -- | Check cluster data for consistency
 checkData :: NodeList -> InstanceList -> NameList -> NameList
           -> ([String], NodeList)