Revision 129734d3 htools/Ganeti/HTools/Cluster.hs

b/htools/Ganeti/HTools/Cluster.hs
75 75

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

  
94 94
-- | Allocation\/relocation solution.
95 95
data AllocSolution = AllocSolution
96
  { asFailures  :: [FailMode]          -- ^ Failure counts
97
  , asAllocs    :: Int                 -- ^ Good allocation count
98
  , asSolutions :: [Node.AllocElement] -- ^ The actual result, length
99
                                       -- of the list depends on the
100
                                       -- allocation/relocation mode
101
  , asLog       :: [String]            -- ^ A list of informational messages
96
  { asFailures :: [FailMode]              -- ^ Failure counts
97
  , asAllocs   :: Int                     -- ^ Good allocation count
98
  , asSolution :: Maybe Node.AllocElement -- ^ The actual allocation result
99
  , asLog      :: [String]                -- ^ Informational messages
102 100
  }
103 101

  
104 102
-- | Node evacuation/group change iallocator result type. This result
......
125 123
-- | The empty solution we start with when computing allocations.
126 124
emptyAllocSolution :: AllocSolution
127 125
emptyAllocSolution = AllocSolution { asFailures = [], asAllocs = 0
128
                                   , asSolutions = [], asLog = [] }
126
                                   , asSolution = Nothing, asLog = [] }
129 127

  
130 128
-- | The empty evac solution.
131 129
emptyEvacSolution :: EvacSolution
......
610 608
concatAllocs as (OpGood ns@(_, _, _, nscore)) =
611 609
    let -- Choose the old or new solution, based on the cluster score
612 610
        cntok = asAllocs as
613
        osols = asSolutions as
611
        osols = asSolution as
614 612
        nsols = case osols of
615
                  [] -> [ns]
616
                  (_, _, _, oscore):[] ->
613
                  Nothing -> Just ns
614
                  Just (_, _, _, oscore) ->
617 615
                      if oscore < nscore
618 616
                      then osols
619
                      else [ns]
620
                  -- FIXME: here we simply concat to lists with more
621
                  -- than one element; we should instead abort, since
622
                  -- this is not a valid usage of this function
623
                  xs -> ns:xs
617
                      else Just ns
624 618
        nsuc = cntok + 1
625 619
    -- Note: we force evaluation of nsols here in order to keep the
626 620
    -- memory profile low - we know that we will need nsols for sure
627 621
    -- in the next cycle, so we force evaluation of nsols, since the
628 622
    -- foldl' in the caller will only evaluate the tuple, but not the
629 623
    -- elements of the tuple
630
    in nsols `seq` nsuc `seq` as { asAllocs = nsuc, asSolutions = nsols }
624
    in nsols `seq` nsuc `seq` as { asAllocs = nsuc, asSolution = nsols }
631 625

  
632 626
-- | Given a solution, generates a reasonable description for it.
633 627
describeSolution :: AllocSolution -> String
634 628
describeSolution as =
635 629
  let fcnt = asFailures as
636
      sols = asSolutions as
630
      sols = asSolution as
637 631
      freasons =
638 632
        intercalate ", " . map (\(a, b) -> printf "%s: %d" (show a) b) .
639 633
        filter ((> 0) . snd) . collapseFailures $ fcnt
640
  in if null sols
641
     then "No valid allocation solutions, failure reasons: " ++
642
          (if null fcnt
643
           then "unknown reasons"
644
           else freasons)
645
     else let (_, _, nodes, cv) = head sols
646
          in printf ("score: %.8f, successes %d, failures %d (%s)" ++
647
                     " for node(s) %s") cv (asAllocs as) (length fcnt) freasons
648
             (intercalate "/" . map Node.name $ nodes)
634
  in case sols of
635
     Nothing -> "No valid allocation solutions, failure reasons: " ++
636
                (if null fcnt then "unknown reasons" else freasons)
637
     Just (_, _, nodes, cv) ->
638
         printf ("score: %.8f, successes %d, failures %d (%s)" ++
639
                 " for node(s) %s") cv (asAllocs as) (length fcnt) freasons
640
               (intercalate "/" . map Node.name $ nodes)
649 641

  
650 642
-- | Annotates a solution with the appropriate string.
651 643
annotateSolution :: AllocSolution -> AllocSolution
......
725 717
          fn accu (gdx, rasol) =
726 718
              case rasol of
727 719
                Bad _ -> accu
728
                Ok sol | null (asSolutions sol) -> accu
720
                Ok sol | isNothing (asSolution sol) -> accu
729 721
                       | unallocable gdx -> accu
730 722
                       | otherwise -> (gdx, sol):accu
731 723

  
......
736 728
sortMGResults gl sols =
737 729
    let extractScore (_, _, _, x) = x
738 730
        solScore (gdx, sol) = (Group.allocPolicy (Container.find gdx gl),
739
                               (extractScore . head . asSolutions) sol)
731
                               (extractScore . fromJust . asSolution) sol)
740 732
    in sortBy (comparing solScore) sols
741 733

  
742 734
-- | Finds the best group for an instance on a multi-group cluster.
......
1150 1142
          newlimit = fmap (flip (-) 1) limit
1151 1143
      in case tryAlloc nl il newi2 allocnodes of
1152 1144
           Bad s -> Bad s
1153
           Ok (AllocSolution { asFailures = errs, asSolutions = sols3 }) ->
1145
           Ok (AllocSolution { asFailures = errs, asSolution = sols3 }) ->
1154 1146
               let newsol = Ok (collapseFailures errs, nl, il, ixes, cstats) in
1155 1147
               case sols3 of
1156
                 [] -> newsol
1157
                 (xnl, xi, _, _):[] ->
1148
                 Nothing -> newsol
1149
                 Just (xnl, xi, _, _) ->
1158 1150
                     if limit == Just 0
1159 1151
                     then newsol
1160 1152
                     else iterateAlloc xnl (Container.add newidx xi il)
1161 1153
                          newlimit newinst allocnodes (xi:ixes)
1162 1154
                          (totalResources xnl:cstats)
1163
                 _ -> Bad "Internal error: multiple solutions for single\
1164
                          \ allocation"
1165 1155

  
1166 1156
-- | The core of the tiered allocation mode.
1167 1157
tieredAlloc :: Node.List

Also available in: Unified diff