, doNextBalance
, tryBalance
, compCV
+ , compDetailedCV
, printStats
, iMoveToJob
-- * IAllocator functions
-- * Allocation functions
, iterateAlloc
, tieredAlloc
+ , tieredSpecMap
+ -- * Node group functions
, instanceGroup
, findSplitInstances
, splitCluster
) where
+import Data.Function (on)
import Data.List
import Data.Ord (comparing)
import Text.Printf (printf)
-- | The complete state for the balancing solution
data Table = Table Node.List Instance.List Score [Placement]
- deriving (Show)
+ deriving (Show, Read)
data CStats = CStats { csFmem :: Int -- ^ Cluster free mem
, csFdsk :: Int -- ^ Cluster free disk
, csScore :: Score -- ^ The cluster score
, csNinst :: Int -- ^ The total number of instances
}
- deriving (Show)
+ deriving (Show, Read)
-- | Currently used, possibly to allocate, unallocable
type AllocStats = (RSpec, RSpec, RSpec)
mem_l = map Node.pMem nodes
dsk_l = map Node.pDsk nodes
-- metric: memory covariance
- mem_cv = varianceCoeff mem_l
+ mem_cv = stdDev mem_l
-- metric: disk covariance
- dsk_cv = varianceCoeff dsk_l
+ dsk_cv = stdDev dsk_l
-- metric: count of instances living on N1 failing nodes
n1_score = fromIntegral . sum . map (\n -> length (Node.sList n) +
length (Node.pList n)) .
filter Node.failN1 $ nodes :: Double
res_l = map Node.pRem nodes
-- metric: reserved memory covariance
- res_cv = varianceCoeff res_l
+ res_cv = stdDev res_l
-- offline instances metrics
offline_ipri = sum . map (length . Node.pList) $ offline
offline_isec = sum . map (length . Node.sList) $ offline
off_pri_score = fromIntegral offline_ipri::Double
cpu_l = map Node.pCpu nodes
-- metric: covariance of vcpu/pcpu ratio
- cpu_cv = varianceCoeff cpu_l
+ cpu_cv = stdDev cpu_l
-- metrics: covariance of cpu, memory, disk and network load
(c_load, m_load, d_load, n_load) = unzip4 $
map (\n ->
pri_tags_inst = sum $ map Node.conflictingPrimaries nodes
pri_tags_score = fromIntegral pri_tags_inst::Double
in [ mem_cv, dsk_cv, n1_score, res_cv, off_score, off_pri_score, cpu_cv
- , varianceCoeff c_load, varianceCoeff m_load
- , varianceCoeff d_load, varianceCoeff n_load
+ , stdDev c_load, stdDev m_load , stdDev d_load, stdDev n_load
, pri_tags_score ]
-- | Compute the /total/ variance.
_ -> Bad "Internal error: multiple solutions for single\
\ allocation"
+-- | The core of the tiered allocation mode
tieredAlloc :: Node.List
-> Instance.List
-> Instance.Instance
Ok newinst' ->
tieredAlloc nl' il' newinst' nreq ixes'
+-- | Compute the tiered spec string description from a list of
+-- allocated instances.
+tieredSpecMap :: [Instance.Instance]
+ -> [String]
+tieredSpecMap trl_ixes =
+ let fin_trl_ixes = reverse trl_ixes
+ ix_byspec = groupBy ((==) `on` Instance.specOf) fin_trl_ixes
+ spec_map = map (\ixs -> (Instance.specOf $ head ixs, length ixs))
+ ix_byspec
+ in map (\(spec, cnt) -> printf "%d,%d,%d=%d" (rspecMem spec)
+ (rspecDsk spec) (rspecCpu spec) cnt) spec_map
+
-- * Formatting functions
-- | Given the original and final nodes, computes the relocation description.
ReplaceAndFailover np -> [ opR np, opF ]
FailoverAndReplace ns -> [ opF, opR ns ]
+-- * Node group functions
+
-- | Computes the group of an instance
instanceGroup :: Node.List -> Instance.Instance -> Result Gdx
instanceGroup nl i =