Revision 61bbbed7

b/htools/Ganeti/HTools/Instance.hs
32 32
    , List
33 33
    , create
34 34
    , instanceRunning
35
    , instanceOffline
36
    , instanceDown
37
    , applyIfOnline
35 38
    , setIdx
36 39
    , setName
37 40
    , setAlias
......
52 55
import qualified Ganeti.HTools.Container as Container
53 56
import qualified Ganeti.Constants as C
54 57

  
58
import Ganeti.HTools.Utils
59

  
55 60
-- * Type declarations
56 61

  
57 62
-- | The instance type.
......
85 90
instanceRunning (Instance {runSt = T.ErrorUp}) = True
86 91
instanceRunning _                               = False
87 92

  
93
-- | Check if instance is offline.
94
instanceOffline :: Instance -> Bool
95
instanceOffline (Instance {runSt = T.AdminOffline}) = True
96
instanceOffline _                                    = False
97

  
98
-- | Check if instance is down.
99
instanceDown :: Instance -> Bool
100
instanceDown inst | instanceRunning inst = False
101
instanceDown inst | instanceOffline inst = False
102
instanceDown _                           = True
103

  
104
-- | Apply the function if the instance is online. Otherwise use
105
-- the initial value
106
applyIfOnline :: Instance -> (a -> a) -> a -> a
107
applyIfOnline = applyIf . not . instanceOffline
108

  
88 109
-- | Constant holding the local storage templates.
89 110
--
90 111
-- /Note:/ Currently Ganeti only exports node total/free disk space
b/htools/Ganeti/HTools/Loader.hs
306 306
        (\ msgs node ->
307 307
             let nname = Node.name node
308 308
                 nilst = map (`Container.find` il) (Node.pList node)
309
                 dilst = filter (not . Instance.instanceRunning) nilst
309
                 dilst = filter Instance.instanceDown nilst
310 310
                 adj_mem = sum . map Instance.mem $ dilst
311 311
                 delta_mem = truncate (Node.tMem node)
312 312
                             - Node.nMem node
......
329 329
nodeImem :: Node.Node -> Instance.List -> Int
330 330
nodeImem node il =
331 331
    let rfind = flip Container.find il
332
    in sum . map (Instance.mem . rfind)
333
           $ Node.pList node
332
        il' = map rfind $ Node.pList node
333
        oil' = filter (not . Instance.instanceOffline) il'
334
    in sum . map Instance.mem $ oil'
335

  
334 336

  
335 337
-- | Compute the amount of disk used by instances on a node (either primary
336 338
-- or secondary).
b/htools/Ganeti/HTools/Node.hs
310 310
removePri t inst =
311 311
    let iname = Instance.idx inst
312 312
        new_plist = delete iname (pList t)
313
        new_mem = fMem t + Instance.mem inst
313
        new_mem = Instance.applyIfOnline inst (+ Instance.mem inst) (fMem t)
314 314
        new_dsk = fDsk t + Instance.dsk inst
315 315
        new_mp = fromIntegral new_mem / tMem t
316 316
        new_dp = fromIntegral new_dsk / tDsk t
317 317
        new_failn1 = new_mem <= rMem t
318
        new_ucpu = uCpu t - Instance.vcpus inst
318
        new_ucpu = Instance.applyIfOnline inst
319
                   (\x -> x - Instance.vcpus inst) (uCpu t)
319 320
        new_rcpu = fromIntegral new_ucpu / tCpu t
320 321
        new_load = utilLoad t `T.subUtil` Instance.util inst
321 322
    in t { pList = new_plist, fMem = new_mem, fDsk = new_dsk
......
374 375
    let iname = Instance.idx inst
375 376
        uses_disk = Instance.usesLocalStorage inst
376 377
        cur_dsk = fDsk t
377
        new_mem = fMem t - Instance.mem inst
378
        new_mem = Instance.applyIfOnline inst
379
                  (\x -> x - Instance.mem inst) (fMem t)
378 380
        new_dsk = if uses_disk
379 381
                  then cur_dsk - Instance.dsk inst
380 382
                  else cur_dsk
381 383
        new_failn1 = new_mem <= rMem t
382
        new_ucpu = uCpu t + Instance.vcpus inst
384
        new_ucpu = Instance.applyIfOnline inst (+ Instance.vcpus inst) (uCpu t)
383 385
        new_pcpu = fromIntegral new_ucpu / tCpu t
384 386
        new_dp = fromIntegral new_dsk / tDsk t
385 387
        l_cpu = mCpu t
......
415 417
        old_peers = peers t
416 418
        old_mem = fMem t
417 419
        new_dsk = fDsk t - Instance.dsk inst
418
        secondary_needed_mem = if Instance.autoBalance inst
420
        secondary_needed_mem = if Instance.autoBalance inst &&
421
                                  not (Instance.instanceOffline inst)
419 422
                               then Instance.mem inst
420 423
                               else 0
421 424
        new_peem = P.find pdx old_peers + secondary_needed_mem
b/htools/Ganeti/HTools/QC.hs
695 695
-- | Check that an instance add with too high memory or disk will be
696 696
-- rejected.
697 697
prop_Node_addPriFM node inst = Instance.mem inst >= Node.fMem node &&
698
                               not (Node.failN1 node)
698
                               not (Node.failN1 node) &&
699
                               not (Instance.instanceOffline inst)
699 700
                               ==>
700 701
                               case Node.addPri node inst'' of
701 702
                                 Types.OpFail Types.FailMem -> True
......
715 716
          inst'' = inst' { Instance.dsk = Instance.dsk inst }
716 717

  
717 718
prop_Node_addPriFC node inst (Positive extra) =
718
    not (Node.failN1 node) ==>
719
    not (Node.failN1 node) &&
720
    not (Instance.instanceOffline inst) ==>
719 721
        case Node.addPri node inst'' of
720 722
          Types.OpFail Types.FailCPU -> True
721 723
          _ -> False
......
726 728
-- | Check that an instance add with too high memory or disk will be
727 729
-- rejected.
728 730
prop_Node_addSec node inst pdx =
729
    (Instance.mem inst >= (Node.fMem node - Node.rMem node) ||
731
    ((Instance.mem inst >= (Node.fMem node - Node.rMem node) &&
732
      not (Instance.instanceOffline inst)) ||
730 733
     Instance.dsk inst >= Node.fDsk node) &&
731 734
    not (Node.failN1 node)
732 735
    ==> isFailure (Node.addSec node inst pdx)
733 736
        where _types = (node::Node.Node, inst::Instance.Instance, pdx::Int)
734 737

  
738
-- | Check that an offline instance with reasonable disk size can always
739
-- be added.
740
prop_Node_addPriOffline node =
741
    forAll (arbitrary `suchThat`
742
            (\ x ->  (Instance.dsk x  < Node.fDsk node) &&
743
                      Instance.instanceOffline x)) $ \inst ->
744
    case Node.addPri node inst of
745
      Types.OpGood _ -> True
746
      _ -> False
747

  
748
prop_Node_addSecOffline node pdx =
749
    forAll (arbitrary `suchThat`
750
            (\ x ->  (Instance.dsk x  < Node.fDsk node) &&
751
                      Instance.instanceOffline x)) $ \inst ->
752
    case Node.addSec node inst pdx of
753
      Types.OpGood _ -> True
754
      _ -> False
755

  
735 756
-- | Checks for memory reservation changes.
736 757
prop_Node_rMem inst =
758
    not (Instance.instanceOffline inst) ==>
737 759
    forAll (arbitrary `suchThat` ((> Types.unitMem) . Node.fMem)) $ \node ->
738 760
    -- ab = auto_balance, nb = non-auto_balance
739 761
    -- we use -1 as the primary node of the instance
......
808 830
              , 'prop_Node_addPriFD
809 831
              , 'prop_Node_addPriFC
810 832
              , 'prop_Node_addSec
833
              , 'prop_Node_addPriOffline
834
              , 'prop_Node_addSecOffline
811 835
              , 'prop_Node_rMem
812 836
              , 'prop_Node_setMdsk
813 837
              , 'prop_Node_tagMaps_idempotent
b/htools/Ganeti/HTools/Utils.hs
30 30
    , stdDev
31 31
    , if'
32 32
    , select
33
    , applyIf
33 34
    , commaJoin
34 35
    , readEitherString
35 36
    , JSRecord
......
76 77

  
77 78
-- * Miscellaneous
78 79

  
80
-- | Apply the function if condition holds, otherwise use default value.
81
applyIf :: Bool -> (a -> a) -> a -> a
82
applyIf b f x = if b then f x else x
83

  
79 84
-- | Comma-join a string list.
80 85
commaJoin :: [String] -> String
81 86
commaJoin = intercalate ","

Also available in: Unified diff