Revision b0631f10 htools/Ganeti/HTools/Cluster.hs

b/htools/Ganeti/HTools/Cluster.hs
74 74
    ) where
75 75

  
76 76
import qualified Data.IntSet as IntSet
77
import Data.Function (on)
78 77
import Data.List
79 78
import Data.Maybe (fromJust, isNothing)
80 79
import Data.Ord (comparing)
81 80
import Text.Printf (printf)
82
import Control.Monad
83 81

  
84 82
import qualified Ganeti.HTools.Container as Container
85 83
import qualified Ganeti.HTools.Instance as Instance
......
116 114

  
117 115
-- | A type denoting the valid allocation mode/pairs.
118 116
--
119
-- For a one-node allocation, this will be a @Left ['Node.Node']@,
120
-- whereas for a two-node allocation, this will be a @Right
121
-- [('Node.Node', 'Node.Node')]@.
122
type AllocNodes = Either [Ndx] [(Ndx, Ndx)]
117
-- For a one-node allocation, this will be a @Left ['Ndx']@, whereas
118
-- for a two-node allocation, this will be a @Right [('Ndx',
119
-- ['Ndx'])]@. In the latter case, the list is basically an
120
-- association list, grouped by primary node and holding the potential
121
-- secondary nodes in the sub-list.
122
type AllocNodes = Either [Ndx] [(Ndx, [Ndx])]
123 123

  
124 124
-- | The empty solution we start with when computing allocations.
125 125
emptyAllocSolution :: AllocSolution
......
682 682
                                 flip Container.find gl . Node.group)
683 683
                    else id
684 684
        all_nodes = filter_fn $ getOnline nl
685
        all_pairs = liftM2 (,) all_nodes all_nodes
686
        ok_pairs = filter (\(x, y) -> Node.idx x /= Node.idx y &&
687
                                      Node.group x == Node.group y) all_pairs
685
        all_pairs = [(Node.idx p,
686
                      [Node.idx s | s <- all_nodes,
687
                                         Node.idx p /= Node.idx s,
688
                                         Node.group p == Node.group s]) |
689
                     p <- all_nodes]
688 690
    in case count of
689 691
         1 -> Ok (Left (map Node.idx all_nodes))
690
         2 -> Ok (Right (map (\(p, s) -> (Node.idx p, Node.idx s)) ok_pairs))
692
         2 -> Ok (Right (filter (not . null . snd) all_pairs))
691 693
         _ -> Bad "Unsupported number of nodes, only one or two  supported"
692 694

  
693 695
-- | Try to allocate an instance on the cluster.
......
698 700
         -> AllocNodes        -- ^ The allocation targets
699 701
         -> m AllocSolution   -- ^ Possible solution list
700 702
tryAlloc nl _ inst (Right ok_pairs) =
701
    let pgroups = groupBy ((==) `on` fst) ok_pairs
702
        psols = parMap rwhnf (foldl' (\cstate (p, s) ->
703
                                      concatAllocs cstate $
704
                                      allocateOnPair nl inst p s)
705
                              emptyAllocSolution) pgroups
703
    let psols = parMap rwhnf (\(p, ss) ->
704
                                  foldl' (\cstate ->
705
                                          concatAllocs cstate .
706
                                          allocateOnPair nl inst p)
707
                                  emptyAllocSolution ss) ok_pairs
706 708
        sols = foldl' sumAllocs emptyAllocSolution psols
707 709
    in if null ok_pairs -- means we have just one node
708 710
       then fail "Not enough online nodes"

Also available in: Unified diff