Revision 88df1fa9

b/htools/Ganeti/HTools/IAlloc.hs
152 152
  let idata = fromJSObject ilist
153 153
  iobj <- mapM (\(x,y) ->
154 154
                    asJSObject y >>= parseInstance ktn x . fromJSObject) idata
155
  let (_, il) = assignIndices iobj
155
  let (kti, il) = assignIndices iobj
156 156
  -- cluster tags
157 157
  ctags <- extrObj "cluster_tags"
158 158
  cdata1 <- mergeData [] [] [] [] (ClusterData gl nl il ctags)
159 159
  let (msgs, fix_nl) = checkData (cdNodes cdata1) (cdInstances cdata1)
160 160
      cdata = cdata1 { cdNodes = fix_nl }
161
      map_n = cdNodes cdata
161 162
      map_i = cdInstances cdata
162 163
      map_g = cdGroups cdata
163 164
  optype <- extrReq "type"
......
170 171
                inew      <- parseBaseInstance rname request
171 172
                let io = snd inew
172 173
                return $ Allocate io req_nodes
174
          | optype == C.iallocatorModeReloc ->
175
              do
176
                rname     <- extrReq "name"
177
                ridx      <- lookupInstance kti rname
178
                req_nodes <- extrReq "required_nodes"
179
                ex_nodes  <- extrReq "relocate_from"
180
                ex_idex   <- mapM (Container.findByName map_n) ex_nodes
181
                return $ Relocate ridx req_nodes (map Node.idx ex_idex)
173 182
          | optype == C.iallocatorModeChgGroup ->
174 183
              do
175 184
                rl_names <- extrReq "instances"
......
237 246
               " were moved successfully"
238 247
    in Ok (info, showJSON (mes, fes, Cluster.esOpCodes es), fin_nl, fin_il)
239 248

  
249
-- | Runs relocate for a single instance.
250
--
251
-- This is wrapper over the 'Cluster.tryNodeEvac' function that is run
252
-- with a single instance (ours), and further it checks that the
253
-- result it got (in the nodes field) is actually consistent, as
254
-- tryNodeEvac is designed to output primarily an opcode list, not a
255
-- node list.
256
processRelocate :: Group.List      -- ^ The group list
257
                -> Node.List       -- ^ The node list
258
                -> Instance.List   -- ^ The instance list
259
                -> Idx             -- ^ The index of the instance to move
260
                -> Int             -- ^ The number of nodes required
261
                -> [Ndx]           -- ^ Nodes which should not be used
262
                -> Result (Node.List, Instance.List, [Ndx]) -- ^ Solution list
263
processRelocate gl nl il idx 1 exndx = do
264
  let orig = Container.find idx il
265
      sorig = Instance.sNode orig
266
  when (exndx /= [sorig]) $
267
       -- FIXME: we can't use the excluded nodes here; the logic is
268
       -- already _but only partially_ implemented in tryNodeEvac...
269
       fail $ "Unsupported request: excluded nodes not equal to\
270
              \ instance's secondary node (" ++ show sorig ++ " versus " ++
271
              show exndx ++ ")"
272
  (nl', il', esol) <- Cluster.tryNodeEvac gl nl il ChangeSecondary [idx]
273
  nodes <- case lookup idx (Cluster.esFailed esol) of
274
             Just msg -> fail msg
275
             Nothing ->
276
                 case lookup idx (map (\(a, _, b) -> (a, b))
277
                                  (Cluster.esMoved esol)) of
278
                   Nothing ->
279
                       fail "Internal error: lost instance idx during move"
280
                   Just n -> return n
281
  let inst = Container.find idx il'
282
      pnode = Instance.pNode inst
283
      snode = Instance.sNode inst
284
  when (snode == sorig) $
285
       fail "Internal error: instance didn't change secondary node?!"
286

  
287
  nodes' <- if (nodes == [pnode, snode])
288
            then return [snode] -- only the new secondary is needed
289
            else fail $ "Internal error: inconsistent node list (" ++
290
                 show nodes ++ ") versus instance nodes (" ++ show pnode ++
291
                 "," ++ show snode ++ ")"
292
  return (nl', il', nodes')
293

  
294
processRelocate _ _ _ _ reqn _ =
295
  fail $ "Exchange " ++ show reqn ++ " nodes mode is not implemented"
296

  
297
formatRelocate :: (Node.List, Instance.List, [Ndx])
298
               -> Result IAllocResult
299
formatRelocate (nl, il, ndxs) =
300
    let nodes = map (`Container.find` nl) ndxs
301
        names = map Node.name nodes
302
    in Ok ("success", showJSON names, nl, il)
303

  
240 304
-- | Process a request and return new node lists.
241 305
processRequest :: Request -> Result IAllocResult
242 306
processRequest request =
......
244 308
  in case rqtype of
245 309
       Allocate xi reqn ->
246 310
           Cluster.tryMGAlloc gl nl il xi reqn >>= formatAllocate il
311
       Relocate idx reqn exnodes ->
312
           processRelocate gl nl il idx reqn exnodes >>= formatRelocate
247 313
       ChangeGroup gdxs idxs ->
248 314
           Cluster.tryChangeGroup gl nl il idxs gdxs >>=
249 315
                  formatNodeEvac gl nl il
b/htools/Ganeti/HTools/Loader.hs
75 75
-}
76 76
data RqType
77 77
    = Allocate Instance.Instance Int -- ^ A new instance allocation
78
    | Relocate Idx Int [Ndx]         -- ^ Choose a new secondary node
78 79
    | NodeEvacuate [Idx] EvacMode    -- ^ node-evacuate mode
79 80
    | ChangeGroup [Gdx] [Idx]        -- ^ Multi-relocate mode
80 81
    deriving (Show, Read)
b/man/hail.rst
37 37
pair; this is the only choice where the algorithm is non-trivial
38 38
with regard to cluster size.
39 39

  
40
For relocations, we try to change the secondary node of the instance to
41
all the valid other nodes; the node which results in the best cluster
42
score is chosen.
43

  
40 44
For node changes (*change-node* mode), we currently support DRBD
41 45
instances only, and all three modes (primary changes, secondary changes
42 46
and all node changes).
......
48 52
is based on the same algorithm as allocations (group with lowest score
49 53
after placement).
50 54

  
51
The deprecated *relocate* and *multi-evacuate* modes are no longer
52
supported.
55
The deprecated *multi-evacuate* modes is no longer supported.
53 56

  
54 57
In all cases, the cluster (or group) scoring is identical to the hbal
55 58
algorithm.

Also available in: Unified diff