465 |
465 |
-- the current candidate target node, generate the possible moves for
|
466 |
466 |
-- a instance.
|
467 |
467 |
possibleMoves :: Bool -- ^ Whether the secondary node is a valid new node
|
|
468 |
-> Bool -- ^ Whether we can change the primary node
|
468 |
469 |
-> Ndx -- ^ Target node candidate
|
469 |
470 |
-> [IMove] -- ^ List of valid result moves
|
470 |
|
possibleMoves True tdx =
|
|
471 |
|
|
472 |
possibleMoves _ False tdx =
|
|
473 |
[ReplaceSecondary tdx]
|
|
474 |
|
|
475 |
possibleMoves True True tdx =
|
471 |
476 |
[ReplaceSecondary tdx,
|
472 |
477 |
ReplaceAndFailover tdx,
|
473 |
478 |
ReplacePrimary tdx,
|
474 |
479 |
FailoverAndReplace tdx]
|
475 |
480 |
|
476 |
|
possibleMoves False tdx =
|
|
481 |
possibleMoves False True tdx =
|
477 |
482 |
[ReplaceSecondary tdx,
|
478 |
483 |
ReplaceAndFailover tdx]
|
479 |
484 |
|
480 |
485 |
-- | Compute the best move for a given instance.
|
481 |
486 |
checkInstanceMove :: [Ndx] -- ^ Allowed target node indices
|
482 |
487 |
-> Bool -- ^ Whether disk moves are allowed
|
|
488 |
-> Bool -- ^ Whether instance moves are allowed
|
483 |
489 |
-> Table -- ^ Original table
|
484 |
490 |
-> Instance.Instance -- ^ Instance to move
|
485 |
491 |
-> Table -- ^ Best new table for this instance
|
486 |
|
checkInstanceMove nodes_idx disk_moves ini_tbl target =
|
|
492 |
checkInstanceMove nodes_idx disk_moves inst_moves ini_tbl target =
|
487 |
493 |
let
|
488 |
494 |
opdx = Instance.pNode target
|
489 |
495 |
osdx = Instance.sNode target
|
490 |
496 |
nodes = filter (\idx -> idx /= opdx && idx /= osdx) nodes_idx
|
491 |
|
use_secondary = elem osdx nodes_idx
|
|
497 |
use_secondary = elem osdx nodes_idx && inst_moves
|
492 |
498 |
aft_failover = if use_secondary -- if allowed to failover
|
493 |
499 |
then checkSingleStep ini_tbl target ini_tbl Failover
|
494 |
500 |
else ini_tbl
|
495 |
501 |
all_moves = if disk_moves
|
496 |
|
then concatMap (possibleMoves use_secondary) nodes
|
|
502 |
then concatMap
|
|
503 |
(possibleMoves use_secondary inst_moves) nodes
|
497 |
504 |
else []
|
498 |
505 |
in
|
499 |
506 |
-- iterate over the possible nodes for this instance
|
... | ... | |
502 |
509 |
-- | Compute the best next move.
|
503 |
510 |
checkMove :: [Ndx] -- ^ Allowed target node indices
|
504 |
511 |
-> Bool -- ^ Whether disk moves are allowed
|
|
512 |
-> Bool -- ^ Whether instance moves are allowed
|
505 |
513 |
-> Table -- ^ The current solution
|
506 |
514 |
-> [Instance.Instance] -- ^ List of instances still to move
|
507 |
515 |
-> Table -- ^ The new solution
|
508 |
|
checkMove nodes_idx disk_moves ini_tbl victims =
|
|
516 |
checkMove nodes_idx disk_moves inst_moves ini_tbl victims =
|
509 |
517 |
let Table _ _ _ ini_plc = ini_tbl
|
510 |
518 |
-- we're using rwhnf from the Control.Parallel.Strategies
|
511 |
519 |
-- package; we don't need to use rnf as that would force too
|
512 |
520 |
-- much evaluation in single-threaded cases, and in
|
513 |
521 |
-- multi-threaded case the weak head normal form is enough to
|
514 |
522 |
-- spark the evaluation
|
515 |
|
tables = parMap rwhnf (checkInstanceMove nodes_idx disk_moves ini_tbl)
|
|
523 |
tables = parMap rwhnf (checkInstanceMove nodes_idx disk_moves
|
|
524 |
inst_moves ini_tbl)
|
516 |
525 |
victims
|
517 |
526 |
-- iterate over all instances, computing the best move
|
518 |
527 |
best_tbl = foldl' compareTables ini_tbl tables
|
... | ... | |
534 |
543 |
-- | Run a balance move
|
535 |
544 |
tryBalance :: Table -- ^ The starting table
|
536 |
545 |
-> Bool -- ^ Allow disk moves
|
|
546 |
-> Bool -- ^ Allow instance moves
|
537 |
547 |
-> Bool -- ^ Only evacuate moves
|
538 |
548 |
-> Score -- ^ Min gain threshold
|
539 |
549 |
-> Score -- ^ Min gain
|
540 |
550 |
-> Maybe Table -- ^ The resulting table and commands
|
541 |
|
tryBalance ini_tbl disk_moves evac_mode mg_limit min_gain =
|
|
551 |
tryBalance ini_tbl disk_moves inst_moves evac_mode mg_limit min_gain =
|
542 |
552 |
let Table ini_nl ini_il ini_cv _ = ini_tbl
|
543 |
553 |
all_inst = Container.elems ini_il
|
544 |
554 |
all_inst' = if evac_mode
|
... | ... | |
551 |
561 |
reloc_inst = filter Instance.movable all_inst'
|
552 |
562 |
node_idx = map Node.idx . filter (not . Node.offline) $
|
553 |
563 |
Container.elems ini_nl
|
554 |
|
fin_tbl = checkMove node_idx disk_moves ini_tbl reloc_inst
|
|
564 |
fin_tbl = checkMove node_idx disk_moves inst_moves ini_tbl reloc_inst
|
555 |
565 |
(Table _ _ fin_cv _) = fin_tbl
|
556 |
566 |
in
|
557 |
567 |
if fin_cv < ini_cv && (ini_cv > mg_limit || ini_cv - fin_cv >= min_gain)
|