Revision 262a08a2 Ganeti/HTools/Cluster.hs
b/Ganeti/HTools/Cluster.hs | ||
---|---|---|
8 | 8 |
module Ganeti.HTools.Cluster |
9 | 9 |
( |
10 | 10 |
-- * Types |
11 |
NodeList |
|
12 |
, InstanceList |
|
13 |
, NameList |
|
11 |
NameList |
|
14 | 12 |
, Placement |
15 | 13 |
, Solution(..) |
16 | 14 |
, Table(..) |
... | ... | |
70 | 68 |
_ -> -1 |
71 | 69 |
|
72 | 70 |
-- | A removal set. |
73 |
data Removal = Removal NodeList [Instance.Instance] |
|
71 |
data Removal = Removal Node.List [Instance.Instance]
|
|
74 | 72 |
|
75 | 73 |
-- | An instance move definition |
76 | 74 |
data IMove = Failover -- ^ Failover the instance (f) |
... | ... | |
81 | 79 |
deriving (Show) |
82 | 80 |
|
83 | 81 |
-- | The complete state for the balancing solution |
84 |
data Table = Table NodeList InstanceList Score [Placement]
|
|
82 |
data Table = Table Node.List Instance.List Score [Placement]
|
|
85 | 83 |
deriving (Show) |
86 | 84 |
|
87 | 85 |
-- General functions |
... | ... | |
103 | 101 |
verifyN1 nl = filter Node.failN1 nl |
104 | 102 |
|
105 | 103 |
{-| Add an instance and return the new node and instance maps. -} |
106 |
addInstance :: NodeList -> Instance.Instance -> |
|
107 |
Node.Node -> Node.Node -> Maybe NodeList |
|
104 |
addInstance :: Node.List -> Instance.Instance ->
|
|
105 |
Node.Node -> Node.Node -> Maybe Node.List
|
|
108 | 106 |
addInstance nl idata pri sec = |
109 | 107 |
let pdx = Node.idx pri |
110 | 108 |
sdx = Node.idx sec |
... | ... | |
116 | 114 |
return new_nl |
117 | 115 |
|
118 | 116 |
-- | Remove an instance and return the new node and instance maps. |
119 |
removeInstance :: NodeList -> Instance.Instance -> NodeList
|
|
117 |
removeInstance :: Node.List -> Instance.Instance -> Node.List
|
|
120 | 118 |
removeInstance nl idata = |
121 | 119 |
let pnode = Instance.pnode idata |
122 | 120 |
snode = Instance.snode idata |
... | ... | |
128 | 126 |
new_nl |
129 | 127 |
|
130 | 128 |
-- | Remove an instance and return the new node map. |
131 |
removeInstances :: NodeList -> [Instance.Instance] -> NodeList
|
|
129 |
removeInstances :: Node.List -> [Instance.Instance] -> Node.List
|
|
132 | 130 |
removeInstances = foldl' removeInstance |
133 | 131 |
|
134 | 132 |
-- | Compute the total free disk and memory in the cluster. |
... | ... | |
148 | 146 |
their new nodes. |
149 | 147 |
|
150 | 148 |
-} |
151 |
applySolution :: NodeList -> InstanceList -> [Placement] -> NodeList
|
|
149 |
applySolution :: Node.List -> Instance.List -> [Placement] -> Node.List
|
|
152 | 150 |
applySolution nl il sol = |
153 | 151 |
let odxes = map (\ (a, b, c, _) -> (Container.find a il, |
154 | 152 |
Node.idx (Container.find b nl), |
... | ... | |
200 | 198 |
those nodes. |
201 | 199 |
|
202 | 200 |
-} |
203 |
computeBadItems :: NodeList -> InstanceList ->
|
|
201 |
computeBadItems :: Node.List -> Instance.List ->
|
|
204 | 202 |
([Node.Node], [Instance.Instance]) |
205 | 203 |
computeBadItems nl il = |
206 | 204 |
let bad_nodes = verifyN1 $ filter (not . Node.offline) $ Container.elems nl |
... | ... | |
218 | 216 |
placement can make this shortcut. |
219 | 217 |
|
220 | 218 |
-} |
221 |
checkRemoval :: NodeList -> [Instance.Instance] -> Maybe Removal |
|
219 |
checkRemoval :: Node.List -> [Instance.Instance] -> Maybe Removal
|
|
222 | 220 |
checkRemoval nl victims = |
223 | 221 |
let nx = removeInstances nl victims |
224 | 222 |
failN1 = verifyN1Check (Container.elems nx) |
... | ... | |
230 | 228 |
|
231 | 229 |
|
232 | 230 |
-- | Computes the removals list for a given depth |
233 |
computeRemovals :: NodeList |
|
231 |
computeRemovals :: Node.List
|
|
234 | 232 |
-> [Instance.Instance] |
235 | 233 |
-> Int |
236 | 234 |
-> [Maybe Removal] |
... | ... | |
281 | 279 |
solution by recursing until all target instances are placed. |
282 | 280 |
|
283 | 281 |
-} |
284 |
checkPlacement :: NodeList -- ^ The current node list |
|
282 |
checkPlacement :: Node.List -- ^ The current node list
|
|
285 | 283 |
-> [Instance.Instance] -- ^ List of instances still to place |
286 | 284 |
-> [Placement] -- ^ Partial solution until now |
287 | 285 |
-> Int -- ^ The delta of the partial solution |
... | ... | |
334 | 332 |
) prev_sol nodes |
335 | 333 |
|
336 | 334 |
-- | Apply a move |
337 |
applyMove :: NodeList -> Instance.Instance |
|
338 |
-> IMove -> (Maybe NodeList, Instance.Instance, Int, Int) |
|
335 |
applyMove :: Node.List -> Instance.Instance
|
|
336 |
-> IMove -> (Maybe Node.List, Instance.Instance, Int, Int)
|
|
339 | 337 |
-- Failover (f) |
340 | 338 |
applyMove nl inst Failover = |
341 | 339 |
let old_pdx = Instance.pnode inst |
... | ... | |
410 | 408 |
Container.addTwo old_sdx new_p old_pdx int_p nl |
411 | 409 |
in (new_nl, Instance.setBoth inst old_sdx new_sdx, old_sdx, new_sdx) |
412 | 410 |
|
413 |
allocateOnSingle :: NodeList -> Instance.Instance -> Node.Node |
|
414 |
-> (Maybe NodeList, Instance.Instance) |
|
411 |
allocateOnSingle :: Node.List -> Instance.Instance -> Node.Node
|
|
412 |
-> (Maybe Node.List, Instance.Instance)
|
|
415 | 413 |
allocateOnSingle nl inst p = |
416 | 414 |
let new_pdx = Node.idx p |
417 | 415 |
new_nl = Node.addPri p inst >>= \new_p -> |
418 | 416 |
return $ Container.add new_pdx new_p nl |
419 | 417 |
in (new_nl, Instance.setBoth inst new_pdx Node.noSecondary) |
420 | 418 |
|
421 |
allocateOnPair :: NodeList -> Instance.Instance -> Node.Node -> Node.Node |
|
422 |
-> (Maybe NodeList, Instance.Instance) |
|
419 |
allocateOnPair :: Node.List -> Instance.Instance -> Node.Node -> Node.Node
|
|
420 |
-> (Maybe Node.List, Instance.Instance)
|
|
423 | 421 |
allocateOnPair nl inst tgt_p tgt_s = |
424 | 422 |
let new_pdx = Node.idx tgt_p |
425 | 423 |
new_sdx = Node.idx tgt_s |
... | ... | |
543 | 541 |
solutionFromRemovals. In case we have no solution, we return Nothing. |
544 | 542 |
|
545 | 543 |
-} |
546 |
computeSolution :: NodeList -- ^ The original node data |
|
544 |
computeSolution :: Node.List -- ^ The original node data
|
|
547 | 545 |
-> [Instance.Instance] -- ^ The list of /bad/ instances |
548 | 546 |
-> Int -- ^ The /depth/ of removals |
549 | 547 |
-> Int -- ^ Maximum number of removals to process |
... | ... | |
604 | 602 |
printf "replace-disks -n %s %s" d i]) |
605 | 603 |
|
606 | 604 |
{-| Converts a placement to string format -} |
607 |
printSolutionLine :: NodeList |
|
608 |
-> InstanceList |
|
605 |
printSolutionLine :: Node.List
|
|
606 |
-> Instance.List
|
|
609 | 607 |
-> Int |
610 | 608 |
-> Int |
611 | 609 |
-> Placement |
... | ... | |
617 | 615 |
(i, p, s, c) = plc |
618 | 616 |
inst = Container.find i il |
619 | 617 |
inam = Instance.name inst |
620 |
npri = cNameOf nl p
|
|
621 |
nsec = cNameOf nl s
|
|
622 |
opri = cNameOf nl $ Instance.pnode inst
|
|
623 |
osec = cNameOf nl $ Instance.snode inst
|
|
618 |
npri = Container.nameOf nl p
|
|
619 |
nsec = Container.nameOf nl s
|
|
620 |
opri = Container.nameOf nl $ Instance.pnode inst
|
|
621 |
osec = Container.nameOf nl $ Instance.snode inst
|
|
624 | 622 |
(moves, cmds) = computeMoves inam opri osec npri nsec |
625 | 623 |
ostr = (printf "%s:%s" opri osec)::String |
626 | 624 |
nstr = (printf "%s:%s" npri nsec)::String |
... | ... | |
640 | 638 |
zip [1..] cmd_strs |
641 | 639 |
|
642 | 640 |
{-| Converts a solution to string format -} |
643 |
printSolution :: NodeList |
|
644 |
-> InstanceList |
|
641 |
printSolution :: Node.List
|
|
642 |
-> Instance.List
|
|
645 | 643 |
-> [Placement] |
646 | 644 |
-> ([String], [[String]]) |
647 | 645 |
printSolution nl il sol = |
648 | 646 |
let |
649 |
nmlen = cMaxNamelen nl
|
|
650 |
imlen = cMaxNamelen il
|
|
647 |
nmlen = Container.maxNameLen nl
|
|
648 |
imlen = Container.maxNameLen il
|
|
651 | 649 |
in |
652 | 650 |
unzip $ map (uncurry $ printSolutionLine nl il nmlen imlen) $ |
653 | 651 |
zip sol [1..] |
654 | 652 |
|
655 | 653 |
-- | Print the node list. |
656 |
printNodes :: NodeList -> String |
|
654 |
printNodes :: Node.List -> String
|
|
657 | 655 |
printNodes nl = |
658 | 656 |
let snl = sortBy (compare `on` Node.idx) (Container.elems nl) |
659 | 657 |
m_name = maximum . map (length . Node.name) $ snl |
... | ... | |
667 | 665 |
in unlines $ (header:map helper snl) |
668 | 666 |
|
669 | 667 |
-- | Compute the mem and disk covariance. |
670 |
compDetailedCV :: NodeList -> (Double, Double, Double, Double, Double) |
|
668 |
compDetailedCV :: Node.List -> (Double, Double, Double, Double, Double)
|
|
671 | 669 |
compDetailedCV nl = |
672 | 670 |
let |
673 | 671 |
all_nodes = Container.elems nl |
... | ... | |
689 | 687 |
in (mem_cv, dsk_cv, n1_score, res_cv, off_score) |
690 | 688 |
|
691 | 689 |
-- | Compute the 'total' variance. |
692 |
compCV :: NodeList -> Double |
|
690 |
compCV :: Node.List -> Double
|
|
693 | 691 |
compCV nl = |
694 | 692 |
let (mem_cv, dsk_cv, n1_score, res_cv, off_score) = compDetailedCV nl |
695 | 693 |
in mem_cv + dsk_cv + n1_score + res_cv + off_score |
696 | 694 |
|
697 |
printStats :: NodeList -> String |
|
695 |
printStats :: Node.List -> String
|
|
698 | 696 |
printStats nl = |
699 | 697 |
let (mem_cv, dsk_cv, n1_score, res_cv, off_score) = compDetailedCV nl |
700 | 698 |
in printf "f_mem=%.8f, r_mem=%.8f, f_dsk=%.8f, n1=%.3f, uf=%.3f" |
Also available in: Unified diff