Revision e08424a8

b/htools/Ganeti/HTools/Cluster.hs
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)
b/htools/Ganeti/HTools/QC.hs
123 123
                      && Node.availMem node > size * Types.unitMem
124 124
                      && Node.availCpu node > size * Types.unitCpu
125 125

  
126
canBalance :: Cluster.Table -> Bool -> Bool -> Bool
127
canBalance tbl dm evac = isJust $ Cluster.tryBalance tbl dm evac 0 0
126
canBalance :: Cluster.Table -> Bool -> Bool -> Bool -> Bool
127
canBalance tbl dm im evac = isJust $ Cluster.tryBalance tbl dm im evac 0 0
128 128

  
129 129
-- | Assigns a new fresh instance to a cluster; this is not
130 130
-- allocation, so no resource checks are done
......
746 746
               (xnl, xi, _, cv):[] ->
747 747
                   let il' = Container.add (Instance.idx xi) xi il
748 748
                       tbl = Cluster.Table xnl il' cv []
749
                   in not (canBalance tbl True False)
749
                   in not (canBalance tbl True True False)
750 750
               _ -> False
751 751

  
752 752
-- | Checks that on a 2-5 node cluster, we can allocate a random
......
815 815
                   let ynl = Container.add (Node.idx hnode) hnode xnl
816 816
                       cv = Cluster.compCV ynl
817 817
                       tbl = Cluster.Table ynl il' cv []
818
                   in canBalance tbl True False
818
                   in canBalance tbl True True False
819 819

  
820 820
-- | Checks consistency
821 821
prop_ClusterCheckConsistency node inst =
b/htools/hbal.hs
109 109
    let Cluster.Table ini_nl ini_il _ _ = ini_tbl
110 110
        allowed_next = Cluster.doNextBalance ini_tbl max_rounds min_score
111 111
        m_fin_tbl = if allowed_next
112
                    then Cluster.tryBalance ini_tbl disk_moves evac_mode
113
                         mg_limit min_gain
112
                    then Cluster.tryBalance ini_tbl disk_moves inst_moves
113
                         evac_mode mg_limit min_gain
114 114
                    else Nothing
115 115
    in
116 116
      case m_fin_tbl of

Also available in: Unified diff