In this way we avoid a circular dependency: tryAlloc depends on the notion of global N+1 redundancy and global N+1 redundancy for plain instances depends on knowing how to allocate an instance on a single node.
Signed-off-by: Klaus Aehlig <[email protected]> --- Makefile.am | 1 + src/Ganeti/HTools/Cluster.hs | 47 ++------------ src/Ganeti/HTools/Cluster/AllocatePrimitives.hs | 85 +++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 42 deletions(-) create mode 100644 src/Ganeti/HTools/Cluster/AllocatePrimitives.hs diff --git a/Makefile.am b/Makefile.am index c4bcf04..546f18a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -910,6 +910,7 @@ HS_LIB_SRCS = \ src/Ganeti/HTools/Backend/Text.hs \ src/Ganeti/HTools/CLI.hs \ src/Ganeti/HTools/Cluster.hs \ + src/Ganeti/HTools/Cluster/AllocatePrimitives.hs \ src/Ganeti/HTools/Cluster/AllocateSecondary.hs \ src/Ganeti/HTools/Cluster/AllocationSolution.hs \ src/Ganeti/HTools/Cluster/Evacuate.hs \ diff --git a/src/Ganeti/HTools/Cluster.hs b/src/Ganeti/HTools/Cluster.hs index 0ad96ab..adfe87d 100644 --- a/src/Ganeti/HTools/Cluster.hs +++ b/src/Ganeti/HTools/Cluster.hs @@ -94,18 +94,18 @@ import Text.Printf (printf) import Ganeti.BasicTypes import Ganeti.HTools.AlgorithmParams (AlgorithmOptions(..), defaultOptions) import qualified Ganeti.HTools.Container as Container +import Ganeti.HTools.Cluster.AllocatePrimitives ( allocateOnSingle + , allocateOnPair) import Ganeti.HTools.Cluster.AllocationSolution - ( AllocElement, GenericAllocSolution(..) , AllocSolution, emptyAllocSolution + ( GenericAllocSolution(..) , AllocSolution, emptyAllocSolution , sumAllocs, extractNl, updateIl , annotateSolution, solutionDescription, collapseFailures , emptyAllocCollection, concatAllocCollections, collectionToSolution ) import Ganeti.HTools.Cluster.Evacuate ( EvacSolution(..), emptyEvacSolution , updateEvacSolution, reverseEvacSolution , nodeEvacInstance) -import Ganeti.HTools.Cluster.Metrics ( compCV, compCVfromStats - , compClusterStatistics - , updateClusterStatisticsTwice) -import Ganeti.HTools.Cluster.Moves (setInstanceLocationScore, applyMoveEx) +import Ganeti.HTools.Cluster.Metrics (compCV, compClusterStatistics) +import Ganeti.HTools.Cluster.Moves (applyMoveEx) import Ganeti.HTools.Cluster.Utils (splitCluster, instancePriGroup , availableGroupNodes, iMoveToJob) import Ganeti.HTools.GlobalN1 (allocGlobalN1, redundant) @@ -116,7 +116,6 @@ import qualified Ganeti.HTools.Group as Group import Ganeti.HTools.Types import Ganeti.Compat import Ganeti.Utils -import Ganeti.Utils.Statistics import Ganeti.Types (EvacMode(..)) -- * Types @@ -314,42 +313,6 @@ compareTables :: Table -> Table -> Table compareTables a@(Table _ _ a_cv _) b@(Table _ _ b_cv _ ) = if a_cv > b_cv then b else a --- | Tries to allocate an instance on one given node. -allocateOnSingle :: AlgorithmOptions - -> Node.List -> Instance.Instance -> Ndx - -> OpResult AllocElement -allocateOnSingle opts nl inst new_pdx = - let p = Container.find new_pdx nl - new_inst = Instance.setBoth inst new_pdx Node.noSecondary - force = algIgnoreSoftErrors opts - in do - Instance.instMatchesPolicy inst (Node.iPolicy p) (Node.exclStorage p) - new_p <- Node.addPriEx force p inst - let new_nl = Container.add new_pdx new_p nl - new_score = compCV new_nl - return (new_nl, new_inst, [new_p], new_score) - --- | Tries to allocate an instance on a given pair of nodes. -allocateOnPair :: AlgorithmOptions - -> [Statistics] - -> Node.List -> Instance.Instance -> Ndx -> Ndx - -> OpResult AllocElement -allocateOnPair opts stats nl inst new_pdx new_sdx = - let tgt_p = Container.find new_pdx nl - tgt_s = Container.find new_sdx nl - force = algIgnoreSoftErrors opts - in do - Instance.instMatchesPolicy inst (Node.iPolicy tgt_p) - (Node.exclStorage tgt_p) - let new_inst = Instance.setBoth (setInstanceLocationScore inst tgt_p tgt_s) - new_pdx new_sdx - new_p <- Node.addPriEx force tgt_p new_inst - new_s <- Node.addSec tgt_s new_inst new_pdx - let new_nl = Container.addTwo new_pdx new_p new_sdx new_s nl - new_stats = updateClusterStatisticsTwice stats - (tgt_p, new_p) (tgt_s, new_s) - return (new_nl, new_inst, [new_p, new_s], compCVfromStats new_stats) - -- | Tries to perform an instance move and returns the best table -- between the original one and the new one. checkSingleStep :: Bool -- ^ Whether to unconditionally ignore soft errors diff --git a/src/Ganeti/HTools/Cluster/AllocatePrimitives.hs b/src/Ganeti/HTools/Cluster/AllocatePrimitives.hs new file mode 100644 index 0000000..3e90e02 --- /dev/null +++ b/src/Ganeti/HTools/Cluster/AllocatePrimitives.hs @@ -0,0 +1,85 @@ +{-| Implementation of the primitives of instance allocation + +-} + +{- + +Copyright (C) 2009, 2010, 2011, 2012, 2013, 2015 Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-} + +module Ganeti.HTools.Cluster.AllocatePrimitives + ( allocateOnSingle + , allocateOnPair + ) where + +import Ganeti.HTools.AlgorithmParams (AlgorithmOptions(..)) +import Ganeti.HTools.Cluster.AllocationSolution (AllocElement) +import Ganeti.HTools.Cluster.Metrics ( compCV, compCVfromStats + , updateClusterStatisticsTwice) +import Ganeti.HTools.Cluster.Moves (setInstanceLocationScore) +import qualified Ganeti.HTools.Container as Container +import qualified Ganeti.HTools.Instance as Instance +import qualified Ganeti.HTools.Node as Node +import Ganeti.HTools.Types +import Ganeti.Utils.Statistics + +-- | Tries to allocate an instance on one given node. +allocateOnSingle :: AlgorithmOptions + -> Node.List -> Instance.Instance -> Ndx + -> OpResult AllocElement +allocateOnSingle opts nl inst new_pdx = + let p = Container.find new_pdx nl + new_inst = Instance.setBoth inst new_pdx Node.noSecondary + force = algIgnoreSoftErrors opts + in do + Instance.instMatchesPolicy inst (Node.iPolicy p) (Node.exclStorage p) + new_p <- Node.addPriEx force p inst + let new_nl = Container.add new_pdx new_p nl + new_score = compCV new_nl + return (new_nl, new_inst, [new_p], new_score) + +-- | Tries to allocate an instance on a given pair of nodes. +allocateOnPair :: AlgorithmOptions + -> [Statistics] + -> Node.List -> Instance.Instance -> Ndx -> Ndx + -> OpResult AllocElement +allocateOnPair opts stats nl inst new_pdx new_sdx = + let tgt_p = Container.find new_pdx nl + tgt_s = Container.find new_sdx nl + force = algIgnoreSoftErrors opts + in do + Instance.instMatchesPolicy inst (Node.iPolicy tgt_p) + (Node.exclStorage tgt_p) + let new_inst = Instance.setBoth (setInstanceLocationScore inst tgt_p tgt_s) + new_pdx new_sdx + new_p <- Node.addPriEx force tgt_p new_inst + new_s <- Node.addSec tgt_s new_inst new_pdx + let new_nl = Container.addTwo new_pdx new_p new_sdx new_s nl + new_stats = updateClusterStatisticsTwice stats + (tgt_p, new_p) (tgt_s, new_s) + return (new_nl, new_inst, [new_p, new_s], compCVfromStats new_stats) -- 2.4.3.573.g4eafbef
