Revision 20b376ff htools/Ganeti/HTools/Cluster.hs

b/htools/Ganeti/HTools/Cluster.hs
65 65
    , tryEvac
66 66
    , tryMGEvac
67 67
    , tryNodeEvac
68
    , tryChangeGroup
68 69
    , collapseFailures
69 70
    -- * Allocation functions
70 71
    , iterateAlloc
......
906 907
failOnSecondaryChange _ _ = return ()
907 908

  
908 909
-- | Run evacuation for a single instance.
910
--
911
-- /Note:/ this function should correctly execute both intra-group
912
-- evacuations (in all modes) and inter-group evacuations (in the
913
-- 'ChangeAll' mode). Of course, this requires that the correct list
914
-- of target nodes is passed.
909 915
nodeEvacInstance :: Node.List         -- ^ The node list (cluster-wide)
910 916
                 -> Instance.List     -- ^ Instance list (cluster-wide)
911 917
                 -> EvacMode          -- ^ The evacuation mode
......
1091 1097
            (map (`Container.find` ini_il) idxs)
1092 1098
    in return $ reverseEvacSolution esol
1093 1099

  
1100
-- | Change-group IAllocator mode main function.
1101
--
1102
-- This is very similar to 'tryNodeEvac', the only difference is that
1103
-- we don't choose as target group the current instance group, but
1104
-- instead:
1105
--
1106
--   1. at the start of the function, we compute which are the target
1107
--   groups; either no groups were passed in, in which case we choose
1108
--   all groups out of which we don't evacuate instance, or there were
1109
--   some groups passed, in which case we use those
1110
--
1111
--   2. for each instance, we use 'findBestAllocGroup' to choose the
1112
--   best group to hold the instance, and then we do what
1113
--   'tryNodeEvac' does, except for this group instead of the current
1114
--   instance group.
1115
--
1116
-- Note that the correct behaviour of this function relies on the
1117
-- function 'nodeEvacInstance' to be able to do correctly both
1118
-- intra-group and inter-group moves when passed the 'ChangeAll' mode.
1119
tryChangeGroup :: Group.List    -- ^ The cluster groups
1120
               -> Node.List     -- ^ The node list (cluster-wide)
1121
               -> Instance.List -- ^ Instance list (cluster-wide)
1122
               -> [Gdx]         -- ^ Target groups; if empty, any
1123
                                -- groups not being evacuated
1124
               -> [Idx]         -- ^ List of instance (indices) to be evacuated
1125
               -> Result EvacSolution
1126
tryChangeGroup gl ini_nl ini_il gdxs idxs =
1127
    let evac_gdxs = nub $ map (instancePriGroup ini_nl .
1128
                               flip Container.find ini_il) idxs
1129
        target_gdxs = (if null gdxs
1130
                       then Container.keys gl
1131
                       else gdxs) \\ evac_gdxs
1132
        offline = map Node.idx . filter Node.offline $ Container.elems ini_nl
1133
        excl_ndx = foldl' (flip IntSet.insert) IntSet.empty offline
1134
        group_ndx = map (\(gdx, (nl, _)) -> (gdx, map Node.idx
1135
                                             (Container.elems nl))) $
1136
                      splitCluster ini_nl ini_il
1137
        (_, _, esol) =
1138
            foldl' (\state@(nl, il, _) inst ->
1139
                        let solution = do
1140
                              let ncnt = Instance.requiredNodes $
1141
                                         Instance.diskTemplate inst
1142
                              (gdx, _, _) <- findBestAllocGroup gl nl il
1143
                                             (Just target_gdxs) inst ncnt
1144
                              av_nodes <- availableGroupNodes group_ndx
1145
                                          excl_ndx gdx
1146
                              nodeEvacInstance nl il ChangeAll inst av_nodes
1147
                        in updateEvacSolution state inst solution
1148
                   )
1149
            (ini_nl, ini_il, emptyEvacSolution)
1150
            (map (`Container.find` ini_il) idxs)
1151
    in return $ reverseEvacSolution esol
1152

  
1153

  
1094 1154
-- | Recursively place instances on the cluster until we're out of space.
1095 1155
iterateAlloc :: Node.List
1096 1156
             -> Instance.List

Also available in: Unified diff