Revision fcfc0c2d

b/src/Ganeti/HTools/Types.hs
53 53
  , unitMem
54 54
  , unitCpu
55 55
  , unitDsk
56
  , unitSpindle
56 57
  , unknownField
57 58
  , Placement
58 59
  , IMove(..)
......
317 318
unitCpu :: Int
318 319
unitCpu = 1
319 320

  
321
-- | Base spindles unit.
322
unitSpindle :: Int
323
unitSpindle = 1
324

  
320 325
-- | Reason for an operation's falure.
321 326
data FailMode = FailMem  -- ^ Failed due to not enough RAM
322 327
              | FailDisk -- ^ Failed due to not enough disk
b/test/hs/Test/Ganeti/HTools/Cluster.hs
106 106
prop_Score_Zero node =
107 107
  forAll (choose (1, 1024)) $ \count ->
108 108
    (not (Node.offline node) && not (Node.failN1 node) && (count > 0) &&
109
     (Node.tDsk node > 0) && (Node.tMem node > 0)) ==>
109
     (Node.tDsk node > 0) && (Node.tMem node > 0) &&
110
     (Node.tSpindles node > 0)) ==>
110 111
  let fn = Node.buildPeers node Container.empty
111 112
      nlst = replicate count fn
112 113
      score = Cluster.compCVNodes nlst
b/test/hs/Test/Ganeti/HTools/Instance.hs
7 7

  
8 8
{-
9 9

  
10
Copyright (C) 2009, 2010, 2011, 2012 Google Inc.
10
Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
11 11

  
12 12
This program is free software; you can redistribute it and/or modify
13 13
it under the terms of the GNU General Public License as published by
......
30 30
  ( testHTools_Instance
31 31
  , genInstanceSmallerThanNode
32 32
  , genInstanceMaybeBiggerThanNode
33
  , genInstanceSmallerThan
34 33
  , genInstanceOnNodeList
35 34
  , genInstanceList
36 35
  , Instance.Instance(..)
37 36
  ) where
38 37

  
38
import Control.Monad (liftM)
39 39
import Test.QuickCheck hiding (Result)
40 40

  
41 41
import Test.Ganeti.TestHelper
......
52 52
-- * Arbitrary instances
53 53

  
54 54
-- | Generates a random instance with maximum disk/mem/cpu values.
55
genInstanceSmallerThan :: Int -> Int -> Int -> Gen Instance.Instance
56
genInstanceSmallerThan lim_mem lim_dsk lim_cpu = do
55
genInstanceSmallerThan :: Int -> Int -> Int -> Maybe Int ->
56
                          Gen Instance.Instance
57
genInstanceSmallerThan lim_mem lim_dsk lim_cpu lim_spin = do
57 58
  name <- genFQDN
58 59
  mem <- choose (0, lim_mem)
59 60
  dsk <- choose (0, lim_dsk)
......
62 63
  sn <- arbitrary
63 64
  vcpus <- choose (0, lim_cpu)
64 65
  dt <- arbitrary
65
  spindles <- arbitrary
66
  spindles <- case lim_spin of
67
    Nothing -> genMaybe $ choose (0, maxSpindles)
68
    Just ls -> liftM Just $ choose (0, ls)
66 69
  let disk = Instance.Disk dsk spindles
67 70
  return $ Instance.create
68 71
    name mem dsk [disk] vcpus run_st [] True pn sn dt 1 []
......
73 76
  genInstanceSmallerThan (Node.availMem node `div` 2)
74 77
                         (Node.availDisk node `div` 2)
75 78
                         (Node.availCpu node `div` 2)
79
                         (if Node.exclStorage node
80
                          then Just $ Node.fSpindles node `div` 2
81
                          else Nothing)
76 82

  
77 83
-- | Generates an instance possibly bigger than a node.
78 84
genInstanceMaybeBiggerThanNode :: Node.Node -> Gen Instance.Instance
......
80 86
  genInstanceSmallerThan (Node.availMem  node + Types.unitMem * 2)
81 87
                         (Node.availDisk node + Types.unitDsk * 3)
82 88
                         (Node.availCpu  node + Types.unitCpu * 4)
89
                         (if Node.exclStorage node
90
                          then Just $ Node.fSpindles node +
91
                               Types.unitSpindle * 5
92
                          else Nothing)
83 93

  
84 94
-- | Generates an instance with nodes on a node list.
85 95
-- The following rules are respected:
......
106 116

  
107 117
-- let's generate a random instance
108 118
instance Arbitrary Instance.Instance where
109
  arbitrary = genInstanceSmallerThan maxMem maxDsk maxCpu
119
  arbitrary = genInstanceSmallerThan maxMem maxDsk maxCpu Nothing
110 120

  
111 121
-- * Test cases
112 122

  
b/test/hs/Test/Ganeti/HTools/Node.hs
69 69
                     -- just by the max... constants)
70 70
        -> Gen Node.Node
71 71
genNode min_multiplier max_multiplier = do
72
  let (base_mem, base_dsk, base_cpu) =
72
  let (base_mem, base_dsk, base_cpu, base_spindles) =
73 73
        case min_multiplier of
74 74
          Just mm -> (mm * Types.unitMem,
75 75
                      mm * Types.unitDsk,
76
                      mm * Types.unitCpu)
77
          Nothing -> (0, 0, 0)
78
      (top_mem, top_dsk, top_cpu)  =
76
                      mm * Types.unitCpu,
77
                      mm)
78
          Nothing -> (0, 0, 0, 0)
79
      (top_mem, top_dsk, top_cpu, top_spindles)  =
79 80
        case max_multiplier of
80 81
          Just mm -> (mm * Types.unitMem,
81 82
                      mm * Types.unitDsk,
82
                      mm * Types.unitCpu)
83
          Nothing -> (maxMem, maxDsk, maxCpu)
83
                      mm * Types.unitCpu,
84
                      mm)
85
          Nothing -> (maxMem, maxDsk, maxCpu, maxSpindles)
84 86
  name  <- genFQDN
85 87
  mem_t <- choose (base_mem, top_mem)
86 88
  mem_f <- choose (base_mem, mem_t)
......
89 91
  dsk_f <- choose (base_dsk, dsk_t)
90 92
  cpu_t <- choose (base_cpu, top_cpu)
91 93
  offl  <- arbitrary
94
  spindles <- choose (base_spindles, top_spindles)
92 95
  let n = Node.create name (fromIntegral mem_t) mem_n mem_f
93
          (fromIntegral dsk_t) dsk_f (fromIntegral cpu_t) offl 1 0 0 False
96
          (fromIntegral dsk_t) dsk_f (fromIntegral cpu_t) offl spindles
97
          0 0 False
94 98
      n' = Node.setPolicy nullIPolicy n
95 99
  return $ Node.buildPeers n' Container.empty
96 100

  
......
101 105
                              not (Node.failN1 n) &&
102 106
                              Node.availDisk n > 0 &&
103 107
                              Node.availMem n > 0 &&
104
                              Node.availCpu n > 0)
108
                              Node.availCpu n > 0 &&
109
                              Node.tSpindles n > 0)
110

  
111
-- | Generate a node with exclusive storage enabled.
112
genExclStorNode :: Gen Node.Node
113
genExclStorNode = do
114
  n <- genOnlineNode
115
  fs <- choose (Types.unitSpindle, Node.tSpindles n)
116
  return n { Node.exclStorage = True
117
           , Node.fSpindles = fs
118
           }
119

  
120
-- | Generate a node with exclusive storage possibly enabled.
121
genMaybeExclStorNode :: Gen Node.Node
122
genMaybeExclStorNode = oneof [genOnlineNode, genExclStorNode]
105 123

  
106 124
-- and a random node
107 125
instance Arbitrary Node.Node where
......
170 188
-- memory does not raise an N+1 error
171 189
prop_addPri_NoN1Fail :: Property
172 190
prop_addPri_NoN1Fail =
173
  forAll genOnlineNode $ \node ->
191
  forAll genMaybeExclStorNode $ \node ->
174 192
  forAll (genInstanceSmallerThanNode node) $ \inst ->
175 193
  let inst' = inst { Instance.mem = Node.fMem node - Node.rMem node }
176 194
  in (Node.addPri node inst' /=? Bad Types.FailN1)
......
201 219
prop_addPriFC :: Property
202 220
prop_addPriFC =
203 221
  forAll (choose (1, maxCpu)) $ \extra ->
204
  forAll genOnlineNode $ \node ->
222
  forAll genMaybeExclStorNode $ \node ->
205 223
  forAll (arbitrary `suchThat` Instance.notOffline) $ \inst ->
206 224
  let inst' = setInstanceSmallerThanNode node inst
207 225
      inst'' = inst' { Instance.vcpus = Node.availCpu node + extra }
......
223 241
-- extra mem/cpu can always be added.
224 242
prop_addOfflinePri :: NonNegative Int -> NonNegative Int -> Property
225 243
prop_addOfflinePri (NonNegative extra_mem) (NonNegative extra_cpu) =
226
  forAll genOnlineNode $ \node ->
244
  forAll genMaybeExclStorNode $ \node ->
227 245
  forAll (genInstanceSmallerThanNode node) $ \inst ->
228 246
  let inst' = inst { Instance.runSt = Types.StatusOffline
229 247
                   , Instance.mem = Node.availMem node + extra_mem
......
237 255
prop_addOfflineSec :: NonNegative Int -> NonNegative Int
238 256
                   -> Types.Ndx -> Property
239 257
prop_addOfflineSec (NonNegative extra_mem) (NonNegative extra_cpu) pdx =
240
  forAll genOnlineNode $ \node ->
258
  forAll genMaybeExclStorNode $ \node ->
241 259
  forAll (genInstanceSmallerThanNode node) $ \inst ->
242 260
  let inst' = inst { Instance.runSt = Types.StatusOffline
243 261
                   , Instance.mem = Node.availMem node + extra_mem
......
251 269
prop_rMem :: Instance.Instance -> Property
252 270
prop_rMem inst =
253 271
  not (Instance.isOffline inst) ==>
254
  forAll (genOnlineNode `suchThat` ((> Types.unitMem) . Node.fMem)) $ \node ->
272
  forAll (genMaybeExclStorNode `suchThat` ((> Types.unitMem) . Node.fMem)) $
273
    \node ->
255 274
  -- ab = auto_balance, nb = non-auto_balance
256 275
  -- we use -1 as the primary node of the instance
257 276
  let inst' = inst { Instance.pNode = -1, Instance.autoBalance = True
......
324 343
-- Check idempotence of add/remove operations
325 344
prop_addPri_idempotent :: Property
326 345
prop_addPri_idempotent =
327
  forAll genOnlineNode $ \node ->
346
  forAll genMaybeExclStorNode $ \node ->
328 347
  forAll (genInstanceSmallerThanNode node) $ \inst ->
329 348
  case Node.addPri node inst of
330 349
    Ok node' -> Node.removePri node' inst ==? node
......
332 351

  
333 352
prop_addSec_idempotent :: Property
334 353
prop_addSec_idempotent =
335
  forAll genOnlineNode $ \node ->
354
  forAll genMaybeExclStorNode $ \node ->
336 355
  forAll (genInstanceSmallerThanNode node) $ \inst ->
337 356
  let pdx = Node.idx node + 1
338 357
      inst' = Instance.setPri inst pdx
b/test/hs/Test/Ganeti/TestCommon.hs
27 27
  ( maxMem
28 28
  , maxDsk
29 29
  , maxCpu
30
  , maxSpindles
30 31
  , maxVcpuRatio
31 32
  , maxSpindleRatio
32 33
  , maxNodes
......
98 99
maxCpu :: Int
99 100
maxCpu = 1024
100 101

  
102
-- | Max spindles (1024, somewhat random value).
103
maxSpindles :: Int
104
maxSpindles = 1024
105

  
101 106
-- | Max vcpu ratio (random value).
102 107
maxVcpuRatio :: Double
103 108
maxVcpuRatio = 1024.0
b/test/hs/Test/Ganeti/TestHTools.hs
119 119
setInstanceSmallerThanNode :: Node.Node
120 120
                           -> Instance.Instance -> Instance.Instance
121 121
setInstanceSmallerThanNode node inst =
122
  inst { Instance.mem = Node.availMem node `div` 2
123
       , Instance.dsk = Node.availDisk node `div` 2
124
       , Instance.vcpus = Node.availCpu node `div` 2
125
       }
122
  let new_dsk = Node.availDisk node `div` 2
123
  in inst { Instance.mem = Node.availMem node `div` 2
124
          , Instance.dsk = new_dsk
125
          , Instance.vcpus = Node.availCpu node `div` 2
126
          , Instance.disks = [Instance.Disk new_dsk
127
                              (if Node.exclStorage node
128
                               then Just $ Node.fSpindles node `div` 2
129
                               else Nothing)]
130
          }

Also available in: Unified diff