{-
-Copyright (C) 2009, 2010, 2011, 2012 Google Inc.
+Copyright (C) 2009, 2010, 2011, 2012, 2013 Google Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
( testHTools_Instance
, genInstanceSmallerThanNode
, genInstanceMaybeBiggerThanNode
- , genInstanceSmallerThan
, genInstanceOnNodeList
, genInstanceList
, Instance.Instance(..)
) where
+import Control.Monad (liftM)
import Test.QuickCheck hiding (Result)
import Test.Ganeti.TestHelper
-- * Arbitrary instances
-- | Generates a random instance with maximum disk/mem/cpu values.
-genInstanceSmallerThan :: Int -> Int -> Int -> Gen Instance.Instance
-genInstanceSmallerThan lim_mem lim_dsk lim_cpu = do
+genInstanceSmallerThan :: Int -> Int -> Int -> Maybe Int ->
+ Gen Instance.Instance
+genInstanceSmallerThan lim_mem lim_dsk lim_cpu lim_spin = do
name <- genFQDN
mem <- choose (0, lim_mem)
dsk <- choose (0, lim_dsk)
sn <- arbitrary
vcpus <- choose (0, lim_cpu)
dt <- arbitrary
- spindles <- arbitrary
+ spindles <- case lim_spin of
+ Nothing -> genMaybe $ choose (0, maxSpindles)
+ Just ls -> liftM Just $ choose (0, ls)
let disk = Instance.Disk dsk spindles
return $ Instance.create
name mem dsk [disk] vcpus run_st [] True pn sn dt 1 []
genInstanceSmallerThan (Node.availMem node `div` 2)
(Node.availDisk node `div` 2)
(Node.availCpu node `div` 2)
+ (if Node.exclStorage node
+ then Just $ Node.fSpindles node `div` 2
+ else Nothing)
-- | Generates an instance possibly bigger than a node.
genInstanceMaybeBiggerThanNode :: Node.Node -> Gen Instance.Instance
genInstanceSmallerThan (Node.availMem node + Types.unitMem * 2)
(Node.availDisk node + Types.unitDsk * 3)
(Node.availCpu node + Types.unitCpu * 4)
+ (if Node.exclStorage node
+ then Just $ Node.fSpindles node +
+ Types.unitSpindle * 5
+ else Nothing)
-- | Generates an instance with nodes on a node list.
-- The following rules are respected:
-- let's generate a random instance
instance Arbitrary Instance.Instance where
- arbitrary = genInstanceSmallerThan maxMem maxDsk maxCpu
+ arbitrary = genInstanceSmallerThan maxMem maxDsk maxCpu Nothing
-- * Test cases
-- just by the max... constants)
-> Gen Node.Node
genNode min_multiplier max_multiplier = do
- let (base_mem, base_dsk, base_cpu) =
+ let (base_mem, base_dsk, base_cpu, base_spindles) =
case min_multiplier of
Just mm -> (mm * Types.unitMem,
mm * Types.unitDsk,
- mm * Types.unitCpu)
- Nothing -> (0, 0, 0)
- (top_mem, top_dsk, top_cpu) =
+ mm * Types.unitCpu,
+ mm)
+ Nothing -> (0, 0, 0, 0)
+ (top_mem, top_dsk, top_cpu, top_spindles) =
case max_multiplier of
Just mm -> (mm * Types.unitMem,
mm * Types.unitDsk,
- mm * Types.unitCpu)
- Nothing -> (maxMem, maxDsk, maxCpu)
+ mm * Types.unitCpu,
+ mm)
+ Nothing -> (maxMem, maxDsk, maxCpu, maxSpindles)
name <- genFQDN
mem_t <- choose (base_mem, top_mem)
mem_f <- choose (base_mem, mem_t)
dsk_f <- choose (base_dsk, dsk_t)
cpu_t <- choose (base_cpu, top_cpu)
offl <- arbitrary
+ spindles <- choose (base_spindles, top_spindles)
let n = Node.create name (fromIntegral mem_t) mem_n mem_f
- (fromIntegral dsk_t) dsk_f (fromIntegral cpu_t) offl 1 0 0 False
+ (fromIntegral dsk_t) dsk_f (fromIntegral cpu_t) offl spindles
+ 0 0 False
n' = Node.setPolicy nullIPolicy n
return $ Node.buildPeers n' Container.empty
not (Node.failN1 n) &&
Node.availDisk n > 0 &&
Node.availMem n > 0 &&
- Node.availCpu n > 0)
+ Node.availCpu n > 0 &&
+ Node.tSpindles n > 0)
+
+-- | Generate a node with exclusive storage enabled.
+genExclStorNode :: Gen Node.Node
+genExclStorNode = do
+ n <- genOnlineNode
+ fs <- choose (Types.unitSpindle, Node.tSpindles n)
+ return n { Node.exclStorage = True
+ , Node.fSpindles = fs
+ }
+
+-- | Generate a node with exclusive storage possibly enabled.
+genMaybeExclStorNode :: Gen Node.Node
+genMaybeExclStorNode = oneof [genOnlineNode, genExclStorNode]
-- and a random node
instance Arbitrary Node.Node where
-- memory does not raise an N+1 error
prop_addPri_NoN1Fail :: Property
prop_addPri_NoN1Fail =
- forAll genOnlineNode $ \node ->
+ forAll genMaybeExclStorNode $ \node ->
forAll (genInstanceSmallerThanNode node) $ \inst ->
let inst' = inst { Instance.mem = Node.fMem node - Node.rMem node }
in (Node.addPri node inst' /=? Bad Types.FailN1)
prop_addPriFC :: Property
prop_addPriFC =
forAll (choose (1, maxCpu)) $ \extra ->
- forAll genOnlineNode $ \node ->
+ forAll genMaybeExclStorNode $ \node ->
forAll (arbitrary `suchThat` Instance.notOffline) $ \inst ->
let inst' = setInstanceSmallerThanNode node inst
inst'' = inst' { Instance.vcpus = Node.availCpu node + extra }
-- extra mem/cpu can always be added.
prop_addOfflinePri :: NonNegative Int -> NonNegative Int -> Property
prop_addOfflinePri (NonNegative extra_mem) (NonNegative extra_cpu) =
- forAll genOnlineNode $ \node ->
+ forAll genMaybeExclStorNode $ \node ->
forAll (genInstanceSmallerThanNode node) $ \inst ->
let inst' = inst { Instance.runSt = Types.StatusOffline
, Instance.mem = Node.availMem node + extra_mem
prop_addOfflineSec :: NonNegative Int -> NonNegative Int
-> Types.Ndx -> Property
prop_addOfflineSec (NonNegative extra_mem) (NonNegative extra_cpu) pdx =
- forAll genOnlineNode $ \node ->
+ forAll genMaybeExclStorNode $ \node ->
forAll (genInstanceSmallerThanNode node) $ \inst ->
let inst' = inst { Instance.runSt = Types.StatusOffline
, Instance.mem = Node.availMem node + extra_mem
prop_rMem :: Instance.Instance -> Property
prop_rMem inst =
not (Instance.isOffline inst) ==>
- forAll (genOnlineNode `suchThat` ((> Types.unitMem) . Node.fMem)) $ \node ->
+ forAll (genMaybeExclStorNode `suchThat` ((> Types.unitMem) . Node.fMem)) $
+ \node ->
-- ab = auto_balance, nb = non-auto_balance
-- we use -1 as the primary node of the instance
let inst' = inst { Instance.pNode = -1, Instance.autoBalance = True
-- Check idempotence of add/remove operations
prop_addPri_idempotent :: Property
prop_addPri_idempotent =
- forAll genOnlineNode $ \node ->
+ forAll genMaybeExclStorNode $ \node ->
forAll (genInstanceSmallerThanNode node) $ \inst ->
case Node.addPri node inst of
Ok node' -> Node.removePri node' inst ==? node
prop_addSec_idempotent :: Property
prop_addSec_idempotent =
- forAll genOnlineNode $ \node ->
+ forAll genMaybeExclStorNode $ \node ->
forAll (genInstanceSmallerThanNode node) $ \inst ->
let pdx = Node.idx node + 1
inst' = Instance.setPri inst pdx