Revision 86c346db

b/src/Ganeti/HTools/Program/Hroller.hs
39 39

  
40 40
import qualified Ganeti.HTools.Container as Container
41 41
import qualified Ganeti.HTools.Node as Node
42
import qualified Ganeti.HTools.Instance as Instance
42 43
import qualified Ganeti.HTools.Group as Group
43 44

  
45
import Ganeti.BasicTypes
44 46
import Ganeti.Common
45 47
import Ganeti.HTools.CLI
46 48
import Ganeti.HTools.ExtLoader
47 49
import Ganeti.HTools.Graph
48 50
import Ganeti.HTools.Loader
51
import Ganeti.HTools.Types
49 52
import Ganeti.Utils
50 53

  
51 54
-- | Options list and functions.
......
74 77
arguments :: [ArgCompletion]
75 78
arguments = []
76 79

  
80
-- | Compute the result of moving an instance to a different node.
81
move :: Idx -> Ndx -> (Node.List, Instance.List)
82
        -> OpResult (Node.List, Instance.List)
83
move idx new_ndx (nl, il) = do
84
  let new_node = Container.find new_ndx nl
85
      inst = Container.find idx il
86
      old_ndx = Instance.pNode inst
87
      old_node = Container.find old_ndx nl
88
  new_node' <- Node.addPriEx True new_node inst
89
  let old_node' = Node.removePri old_node inst
90
      inst' = Instance.setPri inst new_ndx
91
      nl' = Container.addTwo old_ndx old_node' new_ndx new_node' nl
92
      il' = Container.add idx inst' il
93
  return (nl', il')
94

  
95
-- | Move an instance to one of the candidate nodes mentioned.
96
locateInstance :: Idx -> [Ndx] -> (Node.List, Instance.List)
97
                  -> Result (Node.List, Instance.List)
98
locateInstance idx ndxs conf =
99
  msum $ map (opToResult . flip (move idx) conf) ndxs
100

  
101
-- | Move a list of instances to some of the candidate nodes mentioned.
102
locateInstances :: [Idx] -> [Ndx] -> (Node.List, Instance.List)
103
                   -> Result (Node.List, Instance.List)
104
locateInstances idxs ndxs conf =
105
  foldM (\ cf idx -> locateInstance idx ndxs cf) conf idxs
106

  
107
-- | Greedily move the non-redundant instances away from a list of nodes.
108
-- The arguments are the list of nodes to be cleared, a list of nodes the
109
-- instances can be moved to, and an initial configuration. Returned is a
110
-- list of nodes that can be cleared simultaneously and the configuration
111
-- after these nodes are cleared.
112
clearNodes :: [Ndx] -> [Ndx] -> (Node.List, Instance.List)
113
              -> Result ([Ndx], (Node.List, Instance.List))
114
clearNodes [] _ conf = return ([], conf)
115
clearNodes (ndx:ndxs) targets conf = withFirst `mplus` withoutFirst where
116
  withFirst = do
117
     let othernodes = delete ndx targets
118
     conf' <- locateInstances (nonRedundant conf ndx) othernodes conf
119
     (ndxs', conf'') <- clearNodes ndxs othernodes conf'
120
     return (ndx:ndxs', conf'')
121
  withoutFirst = clearNodes ndxs targets conf
122

  
123
-- | Parition a list of nodes into chunks according cluster capacity.
124
partitionNonRedundant :: [Ndx] -> [Ndx] -> (Node.List, Instance.List)
125
                         -> Result [[Ndx]]
126
partitionNonRedundant [] _ _ = return []
127
partitionNonRedundant ndxs targets conf = do
128
  (grp, _) <- clearNodes ndxs targets conf
129
  guard . not . null $ grp
130
  let remaining = ndxs \\ grp
131
  part <- partitionNonRedundant remaining targets conf
132
  return $ grp : part
133

  
77 134
-- | Gather statistics for the coloring algorithms.
78 135
-- Returns a string with a summary on how each algorithm has performed,
79 136
-- in order of non-decreasing effectiveness, and whether it tied or lost
......
179 236
      colorings = map (\(v,a) -> (v,(colorVertMap.a) nodeGraph)) colorAlgorithms
180 237
      smallestColoring =
181 238
        (snd . minimumBy (comparing (IntMap.size . snd))) colorings
182
      idToNode = (`Container.find` nodes)
239
      allNdx = map Node.idx $ Container.elems nlf
240
      splitted = mapM (\ grp -> partitionNonRedundant grp allNdx (nlf,ilf)) $
241
                 IntMap.elems smallestColoring
242
  rebootGroups <- case splitted of
243
                    Ok splitgroups -> return $ concat splitgroups
244
                    Bad _ -> exitErr "Not enough capacity to move non-redundant\ 
245
                                     \ instances"
246
  let idToNode = (`Container.find` nodes)
183 247
      nodesRebootGroups =
184
        map (map idToNode . filter (`IntMap.member` nodes)) $
185
        IntMap.elems smallestColoring
248
        map (map idToNode . filter (`IntMap.member` nodes)) rebootGroups
186 249
      outputRebootGroups = masterLast .
187 250
                           sortBy (flip compare `on` length) $
188 251
                           nodesRebootGroups

Also available in: Unified diff