X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/00b157522469058680f231f51880e720ee48d12c..e4c5beaf3ee5cf16fd40573e3afe9a708b58bb4f:/Ganeti/HTools/Cluster.hs diff --git a/Ganeti/HTools/Cluster.hs b/Ganeti/HTools/Cluster.hs index e3753cc..33d523c 100644 --- a/Ganeti/HTools/Cluster.hs +++ b/Ganeti/HTools/Cluster.hs @@ -32,7 +32,6 @@ module Ganeti.HTools.Cluster , compCV , printStats -- * Loading functions - , loadData , checkData ) where @@ -40,16 +39,14 @@ import Data.List 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 Ganeti.HTools.Types 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 @@ -203,7 +200,7 @@ those nodes. 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 @@ -474,8 +471,10 @@ checkMove nodes_idx ini_tbl victims = -- 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 @@ -687,102 +686,6 @@ printStats nl = -- 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:fo:[]) -> - (name, - if any (== "?") [tm,nm,fm,td,fd] || fo == "Y" then - Node.create 0 0 0 0 0 True - else - Node.create (read tm) (read nm) (read fm) - (read td) (read fd) False - )) - 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 = @@ -798,7 +701,6 @@ nodeIdsk node il = 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)