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