module Ganeti.HTools.Cluster.MetricsComponents
( metricComponents
) where
import Control.Monad (guard)
import Data.Maybe (fromMaybe)
import Language.Haskell.TH
import Ganeti.HTools.Cluster.MetricsTH (MetricComponent(..))
import qualified Ganeti.HTools.Container as Container
import qualified Ganeti.HTools.Node as Node
import qualified Ganeti.HTools.PeerMap as P
import Ganeti.HTools.Types
import Ganeti.Utils.Statistics
type D = Double
metricComponents :: [MetricComponent]
metricComponents =
[ stdDevComp "free_mem_cv" [| 0.5 :: D |] True [| Node.pMem |]
, stdDevComp "free_disk_cv" [| 0.5 :: D |] True [| Node.pDsk |]
, stdDevComp "vcpu_ratio_cv" [| 0.5 :: D |] True
[| Node.pCpuEff |]
, sumComp "spindles_cv" [| 0.5 :: D |] True
[| \n -> Node.instSpindles n / Node.hiSpindles n |]
, sumComp "fail_n1" [| 0.5 :: D |] True
[| \n -> if Node.failN1 n
then toDouble $ length (Node.sList n) + length (Node.pList n)
else 0 |]
, stdDevComp "reserved_mem_cv" [| 1 :: D |] True [| Node.pRem |]
, sumComp "offline_all_cnt" [| 4 :: D |] False
[| \n -> toDouble $ length (Node.pList n) + length (Node.sList n) |]
, sumComp "offline_pri_cnt" [| 16 :: D |] False
[| toDouble . length . Node.pList |]
, stdDevComp "cpu_load_cv" [| 1 :: D |] True
[| \n -> let DynUtil c1 _ _ _ = Node.utilLoad n
DynUtil c2 _ _ _ = Node.utilPool n
in c1/c2 |]
, stdDevComp "mem_load_cv" [| 1 :: D |] True
[| \n -> let DynUtil _ m1 _ _ = Node.utilLoad n
DynUtil _ m2 _ _ = Node.utilPool n
in m1/m2 |]
, stdDevComp "disk_load_cv" [| 1 :: D |] True
[| \n -> let DynUtil _ _ d1 _ = Node.utilLoad n
DynUtil _ _ d2 _ = Node.utilPool n
in d1/d2 |]
, stdDevComp "net_load_cv" [| 1 :: D |] True
[| \n -> let DynUtil _ _ _ n1 = Node.utilLoad n
DynUtil _ _ _ n2 = Node.utilPool n
in n1/n2 |]
, sumComp "pri_tags_score" [| 2 :: D |] True
[| toDouble . Node.conflictingPrimaries |]
, sumComp "location_score" [| 1 :: D |] True
[| toDouble . Node.locationScore |]
, mapComp "location_exclusion_score" [| 0.5 :: D |] True
[| MapData . Node.instanceMap |]
, stdDevComp "free_mem_cv_forth" [| 0.5 :: D |] True
[| Node.pMemForth |]
, stdDevComp "free_disk_cv_forth" [| 0.5 :: D |] True
[| Node.pDskForth |]
, stdDevComp "vcpu_ratio_cv_forth" [| 0.5 :: D |] True
[| Node.pCpuEffForth |]
, sumComp "spindles_cv_forth" [| 0.5 :: D |] True
[| \n -> Node.instSpindlesForth n / Node.hiSpindles n |]
, reservedMemRTotal
]
sumComp :: String -> ExpQ -> Bool -> ExpQ -> MetricComponent
sumComp nm w on f = MetricComponent { name = nm
, weight = w
, fromNode = f
, fromNodeType = [t| Double |]
, statisticsType = [t| SumStat |]
, forOnlineNodes = on
, optimalValue = Nothing
}
stdDevComp :: String -> ExpQ -> Bool -> ExpQ -> MetricComponent
stdDevComp nm w on f = MetricComponent { name = nm
, weight = w
, fromNode = f
, fromNodeType = [t| Double |]
, statisticsType = [t| StdDevStat |]
, forOnlineNodes = on
, optimalValue = Nothing
}
mapComp :: String -> ExpQ -> Bool -> ExpQ -> MetricComponent
mapComp nm w on f = MetricComponent { name = nm
, weight = w
, fromNode = f
, fromNodeType = [t| MapData |]
, statisticsType = [t| MapStat |]
, forOnlineNodes = on
, optimalValue = Nothing
}
wReservedMemRTotal :: Double
wReservedMemRTotal = 0.25
reservedMemRTotal :: MetricComponent
reservedMemRTotal = MetricComponent
{ name = "reserved_mem_rtotal"
, weight = [| wReservedMemRTotal :: D |]
, fromNode = [| Node.pRem |]
, fromNodeType = [t| Double |]
, statisticsType = [t| SumStat |]
, forOnlineNodes = True
, optimalValue = Just [| reservedMemRTotalOptValue |]
}
reservedMemRTotalOptValue :: Node.List -> Double
reservedMemRTotalOptValue nodelist = fromMaybe 0 $ do
let nodes = Container.elems nodelist
guard $ length nodes > 1
let nodeMems = map Node.tMem nodes
totalMem = sum nodeMems
totalMemOneLessNode = totalMem maximum nodeMems
guard $ totalMemOneLessNode > 0
let totalDrbdMem = fromIntegral . sum $ map (P.sumElems . Node.peers) nodes
optimalUsage = totalDrbdMem / totalMem
optimalUsageOneLessNode = totalDrbdMem / totalMemOneLessNode
relativeReserved = optimalUsageOneLessNode optimalUsage
return $ wReservedMemRTotal * relativeReserved