Revision c0501c69

b/Ganeti/HTools/CLI.hs
57 57
    , oINodes
58 58
    , oMaxCpu
59 59
    , oMinDisk
60
    , oDiskMoves
60 61
    , oShowVer
61 62
    , oShowHelp
62 63
    ) where
......
111 112
    , optMinScore  :: Cluster.Score  -- ^ The minimum score we aim for
112 113
    , optMcpu      :: Double         -- ^ Max cpu ratio for nodes
113 114
    , optMdsk      :: Double         -- ^ Max disk usage ratio for nodes
115
    , optDiskMoves :: Bool           -- ^ Allow disk moves
114 116
    , optVerbose   :: Int            -- ^ Verbosity level
115 117
    , optShowVer   :: Bool           -- ^ Just show the program version
116 118
    , optShowHelp  :: Bool           -- ^ Just show the help
......
140 142
 , optMinScore  = 1e-9
141 143
 , optMcpu      = -1
142 144
 , optMdsk      = -1
145
 , optDiskMoves = True
143 146
 , optVerbose   = 1
144 147
 , optShowVer   = False
145 148
 , optShowHelp  = False
......
259 262
           (ReqArg (\ n opts -> opts { optMdsk = read n }) "RATIO")
260 263
           "minimum free disk space for nodes (between 0 and 1)"
261 264

  
265
oDiskMoves :: OptType
266
oDiskMoves = Option "" ["no-disk-moves"]
267
             (NoArg (\ opts -> opts { optDiskMoves = False}))
268
             "disallow disk moves from the list of allowed instance changes,\
269
             \ thus allowing only the 'cheap' failover/migrate operations"
270

  
262 271
oShowVer :: OptType
263 272
oShowVer = Option "V" ["version"]
264 273
           (NoArg (\ opts -> opts { optShowVer = True}))
b/Ganeti/HTools/Cluster.hs
381 381
            in
382 382
              compareTables cur_tbl upd_tbl
383 383

  
384
-- | Given the status of the current secondary as a valid new node
385
-- and the current candidate target node,
386
-- generate the possible moves for a instance.
387
possibleMoves :: Bool -> Ndx -> [IMove]
384
-- | Given the status of the current secondary as a valid new node and
385
-- the current candidate target node, generate the possible moves for
386
-- a instance.
387
possibleMoves :: Bool      -- ^ Whether the secondary node is a valid new node
388
              -> Ndx       -- ^ Target node candidate
389
              -> [IMove]   -- ^ List of valid result moves
388 390
possibleMoves True tdx =
389 391
    [ReplaceSecondary tdx,
390 392
     ReplaceAndFailover tdx,
......
396 398
     ReplaceAndFailover tdx]
397 399

  
398 400
-- | Compute the best move for a given instance.
399
checkInstanceMove :: [Ndx]             -- Allowed target node indices
400
                  -> Table             -- Original table
401
                  -> Instance.Instance -- Instance to move
402
                  -> Table             -- Best new table for this instance
403
checkInstanceMove nodes_idx ini_tbl target =
401
checkInstanceMove :: [Ndx]             -- ^ Allowed target node indices
402
                  -> Bool              -- ^ Whether disk moves are allowed
403
                  -> Table             -- ^ Original table
404
                  -> Instance.Instance -- ^ Instance to move
405
                  -> Table             -- ^ Best new table for this instance
406
checkInstanceMove nodes_idx disk_moves ini_tbl target =
404 407
    let
405 408
        opdx = Instance.pnode target
406 409
        osdx = Instance.snode target
......
409 412
        aft_failover = if use_secondary -- if allowed to failover
410 413
                       then checkSingleStep ini_tbl target ini_tbl Failover
411 414
                       else ini_tbl
412
        all_moves = concatMap (possibleMoves use_secondary) nodes
415
        all_moves = if disk_moves
416
                    then concatMap (possibleMoves use_secondary) nodes
417
                    else []
413 418
    in
414 419
      -- iterate over the possible nodes for this instance
415 420
      foldl' (checkSingleStep ini_tbl target) aft_failover all_moves
416 421

  
417 422
-- | Compute the best next move.
418 423
checkMove :: [Ndx]               -- ^ Allowed target node indices
424
          -> Bool                -- ^ Whether disk moves are allowed
419 425
          -> Table               -- ^ The current solution
420 426
          -> [Instance.Instance] -- ^ List of instances still to move
421 427
          -> Table               -- ^ The new solution
422
checkMove nodes_idx ini_tbl victims =
428
checkMove nodes_idx disk_moves ini_tbl victims =
423 429
    let Table _ _ _ ini_plc = ini_tbl
424 430
        -- iterate over all instances, computing the best move
425 431
        best_tbl =
......
427 433
            (\ step_tbl elem ->
428 434
                 if Instance.snode elem == Node.noSecondary then step_tbl
429 435
                    else compareTables step_tbl $
430
                         checkInstanceMove nodes_idx ini_tbl elem)
436
                         checkInstanceMove nodes_idx disk_moves ini_tbl elem)
431 437
            ini_tbl victims
432 438
        Table _ _ _ best_plc = best_tbl
433 439
    in
b/hbal.1
27 27
.BI "[ -l " limit " ]"
28 28
.BI "[ -e " score " ]"
29 29
.BI "[ -O " name... " ]"
30
.B "[ --no-disk-moves ]"
30 31

  
31 32
.TP
32 33
Reporting options:
......
303 304
.RE
304 305

  
305 306
.TP
307
.BI "--no-disk-moves"
308
This parameter prevent hbal from using disk move (i.e. "gnt-instance
309
replace-disks") operations. This will result in a much quicker
310
balancing, but of course the improvements are limited. It is up to the
311
user to decide when to use one or another.
312

  
313
.TP
306 314
.BI "-n" nodefile ", --nodes=" nodefile
307 315
The name of the file holding node information (if not collecting via
308 316
RAPI), instead of the default \fInodes\fR file (but see below how to
b/hbal.hs
59 59
    , oMinScore
60 60
    , oMaxCpu
61 61
    , oMinDisk
62
    , oDiskMoves
62 63
    , oShowVer
63 64
    , oShowHelp
64 65
    ]
......
69 70
-}
70 71
iterateDepth :: Cluster.Table    -- ^ The starting table
71 72
             -> Int              -- ^ Remaining length
73
             -> Bool             -- ^ Allow disk moves
72 74
             -> Int              -- ^ Max node name len
73 75
             -> Int              -- ^ Max instance name len
74 76
             -> [[String]]       -- ^ Current command list
......
76 78
             -> Cluster.Score    -- ^ Score at which to stop
77 79
             -> IO (Cluster.Table, [[String]]) -- ^ The resulting table and
78 80
                                               -- commands
79
iterateDepth ini_tbl max_rounds nmlen imlen
81
iterateDepth ini_tbl max_rounds disk_moves nmlen imlen
80 82
             cmd_strs oneline min_score =
81 83
    let Cluster.Table ini_nl ini_il ini_cv ini_plc = ini_tbl
82 84
        all_inst = Container.elems ini_il
83 85
        node_idx = map Node.idx . filter (not . Node.offline) $
84 86
                   Container.elems ini_nl
85
        fin_tbl = Cluster.checkMove node_idx ini_tbl all_inst
87
        fin_tbl = Cluster.checkMove node_idx disk_moves ini_tbl all_inst
86 88
        (Cluster.Table _ _ fin_cv fin_plc) = fin_tbl
87 89
        ini_plc_len = length ini_plc
88 90
        fin_plc_len = length fin_plc
......
98 100
          hFlush stdout
99 101
        (if fin_cv < ini_cv then -- this round made success, try deeper
100 102
             if allowed_next && fin_cv > min_score
101
             then iterateDepth fin_tbl max_rounds
103
             then iterateDepth fin_tbl max_rounds disk_moves
102 104
                  nmlen imlen upd_cmd_strs oneline min_score
103 105
             -- don't go deeper, but return the better solution
104 106
             else return (fin_tbl, upd_cmd_strs)
......
196 198
      nmlen = Container.maxNameLen nl
197 199

  
198 200
  (fin_tbl, cmd_strs) <- iterateDepth ini_tbl (optMaxLength opts)
201
                         (optDiskMoves opts)
199 202
                         nmlen imlen [] oneline min_cv
200 203
  let (Cluster.Table fin_nl _ fin_cv fin_plc) = fin_tbl
201 204
      ord_plc = reverse fin_plc

Also available in: Unified diff