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