Revision 5a13489b
b/lib/cmdlib/common.py | ||
---|---|---|
544 | 544 |
@see: L{ComputeIPolicySpecViolation} |
545 | 545 |
|
546 | 546 |
""" |
547 |
ret = [] |
|
547 | 548 |
be_full = cfg.GetClusterInfo().FillBE(instance) |
548 | 549 |
mem_size = be_full[constants.BE_MAXMEM] |
549 | 550 |
cpu_count = be_full[constants.BE_VCPUS] |
550 |
spindle_use = be_full[constants.BE_SPINDLE_USE] |
|
551 |
es_flags = rpc.GetExclusiveStorageForNodeNames(cfg, instance.all_nodes) |
|
552 |
if any(es_flags.values()): |
|
553 |
# With exclusive storage use the actual spindles |
|
554 |
try: |
|
555 |
spindle_use = sum([disk.spindles for disk in instance.disks]) |
|
556 |
except TypeError: |
|
557 |
ret.append("Number of spindles not configured for disks of instance %s" |
|
558 |
" while exclusive storage is enabled, try running gnt-cluster" |
|
559 |
" repair-disk-sizes" % instance.name) |
|
560 |
# _ComputeMinMaxSpec ignores 'None's |
|
561 |
spindle_use = None |
|
562 |
else: |
|
563 |
spindle_use = be_full[constants.BE_SPINDLE_USE] |
|
551 | 564 |
disk_count = len(instance.disks) |
552 | 565 |
disk_sizes = [disk.size for disk in instance.disks] |
553 | 566 |
nic_count = len(instance.nics) |
554 | 567 |
disk_template = instance.disk_template |
555 | 568 |
|
556 |
return _compute_fn(ipolicy, mem_size, cpu_count, disk_count, nic_count, |
|
557 |
disk_sizes, spindle_use, disk_template) |
|
569 |
return ret + _compute_fn(ipolicy, mem_size, cpu_count, disk_count, nic_count,
|
|
570 |
disk_sizes, spindle_use, disk_template)
|
|
558 | 571 |
|
559 | 572 |
|
560 | 573 |
def _ComputeViolatingInstances(ipolicy, instances, cfg): |
b/src/Ganeti/HTools/Cluster.hs | ||
---|---|---|
489 | 489 |
let p = Container.find new_pdx nl |
490 | 490 |
new_inst = Instance.setBoth inst new_pdx Node.noSecondary |
491 | 491 |
in do |
492 |
Instance.instMatchesPolicy inst (Node.iPolicy p) |
|
492 |
Instance.instMatchesPolicy inst (Node.iPolicy p) (Node.exclStorage p)
|
|
493 | 493 |
new_p <- Node.addPri p inst |
494 | 494 |
let new_nl = Container.add new_pdx new_p nl |
495 | 495 |
new_score = compCV new_nl |
... | ... | |
503 | 503 |
tgt_s = Container.find new_sdx nl |
504 | 504 |
in do |
505 | 505 |
Instance.instMatchesPolicy inst (Node.iPolicy tgt_p) |
506 |
(Node.exclStorage tgt_p) |
|
506 | 507 |
new_p <- Node.addPri tgt_p inst |
507 | 508 |
new_s <- Node.addSec tgt_s inst new_pdx |
508 | 509 |
let new_inst = Instance.setBoth inst new_pdx new_sdx |
b/src/Ganeti/HTools/Instance.hs | ||
---|---|---|
59 | 59 |
, mirrorType |
60 | 60 |
) where |
61 | 61 |
|
62 |
import Control.Monad (liftM2) |
|
63 |
|
|
62 | 64 |
import Ganeti.BasicTypes |
63 | 65 |
import qualified Ganeti.HTools.Types as T |
64 | 66 |
import qualified Ganeti.HTools.Container as Container |
... | ... | |
278 | 280 |
-- | Checks if an instance is smaller/bigger than a given spec. Returns |
279 | 281 |
-- OpGood for a correct spec, otherwise Bad one of the possible |
280 | 282 |
-- failure modes. |
281 |
instCompareISpec :: Ordering -> Instance-> T.ISpec -> T.OpResult () |
|
282 |
instCompareISpec which inst ispec |
|
283 |
instCompareISpec :: Ordering -> Instance-> T.ISpec -> Bool -> T.OpResult ()
|
|
284 |
instCompareISpec which inst ispec exclstor
|
|
283 | 285 |
| which == mem inst `compare` T.iSpecMemorySize ispec = Bad T.FailMem |
284 | 286 |
| which `elem` map ((`compare` T.iSpecDiskSize ispec) . dskSize) |
285 | 287 |
(disks inst) = Bad T.FailDisk |
286 | 288 |
| which == vcpus inst `compare` T.iSpecCpuCount ispec = Bad T.FailCPU |
287 |
| which == spindleUse inst `compare` T.iSpecSpindleUse ispec |
|
289 |
| exclstor && |
|
290 |
case getTotalSpindles inst of |
|
291 |
Nothing -> True |
|
292 |
Just sp_sum -> which == sp_sum `compare` T.iSpecSpindleUse ispec |
|
293 |
= Bad T.FailSpindles |
|
294 |
| not exclstor && which == spindleUse inst `compare` T.iSpecSpindleUse ispec |
|
288 | 295 |
= Bad T.FailSpindles |
289 | 296 |
| diskTemplate inst /= T.DTDiskless && |
290 | 297 |
which == length (disks inst) `compare` T.iSpecDiskCount ispec |
... | ... | |
292 | 299 |
| otherwise = Ok () |
293 | 300 |
|
294 | 301 |
-- | Checks if an instance is smaller than a given spec. |
295 |
instBelowISpec :: Instance -> T.ISpec -> T.OpResult () |
|
302 |
instBelowISpec :: Instance -> T.ISpec -> Bool -> T.OpResult ()
|
|
296 | 303 |
instBelowISpec = instCompareISpec GT |
297 | 304 |
|
298 | 305 |
-- | Checks if an instance is bigger than a given spec. |
299 |
instAboveISpec :: Instance -> T.ISpec -> T.OpResult () |
|
306 |
instAboveISpec :: Instance -> T.ISpec -> Bool -> T.OpResult ()
|
|
300 | 307 |
instAboveISpec = instCompareISpec LT |
301 | 308 |
|
302 | 309 |
-- | Checks if an instance matches a min/max specs pair |
303 |
instMatchesMinMaxSpecs :: Instance -> T.MinMaxISpecs -> T.OpResult () |
|
304 |
instMatchesMinMaxSpecs inst minmax = do |
|
305 |
instAboveISpec inst (T.minMaxISpecsMinSpec minmax) |
|
306 |
instBelowISpec inst (T.minMaxISpecsMaxSpec minmax) |
|
310 |
instMatchesMinMaxSpecs :: Instance -> T.MinMaxISpecs -> Bool -> T.OpResult ()
|
|
311 |
instMatchesMinMaxSpecs inst minmax exclstor = do
|
|
312 |
instAboveISpec inst (T.minMaxISpecsMinSpec minmax) exclstor
|
|
313 |
instBelowISpec inst (T.minMaxISpecsMaxSpec minmax) exclstor
|
|
307 | 314 |
|
308 | 315 |
-- | Checks if an instance matches any specs of a policy |
309 |
instMatchesSpecs :: Instance -> [T.MinMaxISpecs] -> T.OpResult () |
|
316 |
instMatchesSpecs :: Instance -> [T.MinMaxISpecs] -> Bool -> T.OpResult ()
|
|
310 | 317 |
-- Return Ok for no constraints, though this should never happen |
311 |
instMatchesSpecs _ [] = Ok () |
|
312 |
instMatchesSpecs inst minmaxes = |
|
318 |
instMatchesSpecs _ [] _ = Ok ()
|
|
319 |
instMatchesSpecs inst minmaxes exclstor =
|
|
313 | 320 |
-- The initial "Bad" should be always replaced by a real result |
314 | 321 |
foldr eithermatch (Bad T.FailInternal) minmaxes |
315 |
where eithermatch mm (Bad _) = instMatchesMinMaxSpecs inst mm |
|
322 |
where eithermatch mm (Bad _) = instMatchesMinMaxSpecs inst mm exclstor
|
|
316 | 323 |
eithermatch _ y@(Ok ()) = y |
317 | 324 |
|
318 | 325 |
-- | Checks if an instance matches a policy. |
319 |
instMatchesPolicy :: Instance -> T.IPolicy -> T.OpResult () |
|
320 |
instMatchesPolicy inst ipol = do |
|
321 |
instMatchesSpecs inst $ T.iPolicyMinMaxISpecs ipol
|
|
326 |
instMatchesPolicy :: Instance -> T.IPolicy -> Bool -> T.OpResult ()
|
|
327 |
instMatchesPolicy inst ipol exclstor = do
|
|
328 |
instMatchesSpecs inst (T.iPolicyMinMaxISpecs ipol) exclstor
|
|
322 | 329 |
if diskTemplate inst `elem` T.iPolicyDiskTemplates ipol |
323 | 330 |
then Ok () |
324 | 331 |
else Bad T.FailDisk |
b/test/hs/Test/Ganeti/HTools/Cluster.hs | ||
---|---|---|
394 | 394 |
forAll genOnlineNode $ \node -> |
395 | 395 |
forAll (choose (5, 20)) $ \count -> |
396 | 396 |
forAll (genInstanceSmallerThanNode node) $ \inst -> |
397 |
forAll (arbitrary `suchThat` (isBad . |
|
398 |
Instance.instMatchesPolicy inst)) $ \ipol -> |
|
397 |
forAll (arbitrary `suchThat` |
|
398 |
(isBad . flip (Instance.instMatchesPolicy inst) |
|
399 |
(Node.exclStorage node))) $ \ipol -> |
|
399 | 400 |
let rqn = Instance.requiredNodes $ Instance.diskTemplate inst |
400 | 401 |
node' = Node.setPolicy ipol node |
401 | 402 |
nl = makeSmallCluster node' count |
b/test/py/ganeti.cmdlib_unittest.py | ||
---|---|---|
827 | 827 |
|
828 | 828 |
|
829 | 829 |
class _FakeConfigForComputeIPolicyInstanceViolation: |
830 |
def __init__(self, be): |
|
830 |
def __init__(self, be, excl_stor):
|
|
831 | 831 |
self.cluster = objects.Cluster(beparams={"default": be}) |
832 |
self.excl_stor = excl_stor |
|
832 | 833 |
|
833 | 834 |
def GetClusterInfo(self): |
834 | 835 |
return self.cluster |
835 | 836 |
|
837 |
def GetNodeInfo(self, _): |
|
838 |
return {} |
|
839 |
|
|
840 |
def GetNdParams(self, _): |
|
841 |
return { |
|
842 |
constants.ND_EXCLUSIVE_STORAGE: self.excl_stor, |
|
843 |
} |
|
844 |
|
|
836 | 845 |
|
837 | 846 |
class TestComputeIPolicyInstanceViolation(unittest.TestCase): |
838 | 847 |
def test(self): |
... | ... | |
841 | 850 |
constants.BE_VCPUS: 2, |
842 | 851 |
constants.BE_SPINDLE_USE: 4, |
843 | 852 |
} |
844 |
disks = [objects.Disk(size=512)] |
|
845 |
cfg = _FakeConfigForComputeIPolicyInstanceViolation(beparams) |
|
853 |
disks = [objects.Disk(size=512, spindles=13)]
|
|
854 |
cfg = _FakeConfigForComputeIPolicyInstanceViolation(beparams, False)
|
|
846 | 855 |
instance = objects.Instance(beparams=beparams, disks=disks, nics=[], |
847 | 856 |
disk_template=constants.DT_PLAIN) |
848 | 857 |
stub = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 4, |
... | ... | |
855 | 864 |
ret = common.ComputeIPolicyInstanceViolation(NotImplemented, instance2, |
856 | 865 |
cfg, _compute_fn=stub) |
857 | 866 |
self.assertEqual(ret, []) |
867 |
cfg_es = _FakeConfigForComputeIPolicyInstanceViolation(beparams, True) |
|
868 |
stub_es = _StubComputeIPolicySpecViolation(2048, 2, 1, 0, [512], 13, |
|
869 |
constants.DT_PLAIN) |
|
870 |
ret = common.ComputeIPolicyInstanceViolation(NotImplemented, instance, |
|
871 |
cfg_es, _compute_fn=stub_es) |
|
872 |
self.assertEqual(ret, []) |
|
873 |
ret = common.ComputeIPolicyInstanceViolation(NotImplemented, instance2, |
|
874 |
cfg_es, _compute_fn=stub_es) |
|
875 |
self.assertEqual(ret, []) |
|
858 | 876 |
|
859 | 877 |
|
860 | 878 |
class TestComputeIPolicyInstanceSpecViolation(unittest.TestCase): |
Also available in: Unified diff