Also support obtaining memory data in the mond backend of the htools, by using the output provided by the kvm RSS data collector.
Signed-off-by: Klaus Aehlig <[email protected]> --- src/Ganeti/HTools/Backend/MonD.hs | 61 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/src/Ganeti/HTools/Backend/MonD.hs b/src/Ganeti/HTools/Backend/MonD.hs index ad7e490..ea1a31c 100644 --- a/src/Ganeti/HTools/Backend/MonD.hs +++ b/src/Ganeti/HTools/Backend/MonD.hs @@ -48,6 +48,7 @@ module Ganeti.HTools.Backend.MonD , mkReport , totalCPUCollector , xenCPUCollector + , kvmRSSCollector ) where import Control.Monad @@ -63,8 +64,9 @@ import qualified Text.JSON as J import Ganeti.BasicTypes import qualified Ganeti.Constants as C import Ganeti.Cpu.Types -import qualified Ganeti.DataCollectors.XenCpuLoad as XenCpuLoad import qualified Ganeti.DataCollectors.CPUload as CPUload +import qualified Ganeti.DataCollectors.KvmRSS as KvmRSS +import qualified Ganeti.DataCollectors.XenCpuLoad as XenCpuLoad import Ganeti.DataCollectors.Types ( DCReport, DCCategory , dcReportData, dcReportName , getCategoryName ) @@ -83,6 +85,7 @@ import Ganeti.Utils (exitIfBad) -- | The actual data types for MonD's Data Collectors. data Report = CPUavgloadReport CPUavgload | InstanceCpuReport (Map.Map String Double) + | InstanceRSSReport (Map.Map String Double) -- | Type describing a data collector basic information. data DataCollector = DataCollector @@ -195,14 +198,66 @@ xenCPUCollector = DataCollector { dName = XenCpuLoad.dcName , dUse = useInstanceCpuData } +-- * kvm instance RSS collector + +-- | Parse results of the kvm instance RSS data Collector +mkKvmRSSReport :: DCReport -> Maybe Report +mkKvmRSSReport = + liftM InstanceRSSReport . maybeParseMap . dcReportData + +-- | Update cluster data based on per-instance RSS data. +-- Also set the node's memoy util pool correctly. Our unit +-- of memory usage is pages; there are 256 pages per MiB +-- of node memory not used by the node itself. +useInstanceRSSData :: [(Node.Node, Report)] + -> (Node.List, Instance.List) + -> Result (Node.List, Instance.List) +useInstanceRSSData reports (nl, il) = do + let toMap (InstanceRSSReport m) = Just m + toMap _ = Nothing + let usage = Map.unions $ mapMaybe (toMap . snd) reports + missingData = (Set.fromList . map Instance.name $ IntMap.elems il) + Set.\\ Map.keysSet usage + unless (Set.null missingData) + . Bad . (++) "No RSS information available for " + . show $ Set.elems missingData + let updateInstance inst = + let mem = Map.lookup (Instance.name inst) usage + dynU = Instance.util inst + dynU' = maybe dynU (\m -> dynU { memWeight = m }) mem + in inst { Instance.util = dynU' } + let il' = IntMap.map updateInstance il + let updateNode node = + let mem = sum + . map (\ idx -> maybe 0 (memWeight . Instance.util) + $ IntMap.lookup idx il') + $ Node.pList node + dynU = Node.utilLoad node + dynU' = dynU { memWeight = mem } + pool = Node.utilPool node + nodePages = (Node.tMem node - fromIntegral (Node.nMem node)) * 256.0 + pool' = pool { memWeight = nodePages } + in node { Node.utilLoad = dynU', Node.utilPool = pool' } + let nl' = IntMap.map updateNode nl + return (nl', il') + +-- | Update cluster data based on the per-instance CPU usage +kvmRSSCollector :: DataCollector +kvmRSSCollector = DataCollector { dName = KvmRSS.dcName + , dCategory = KvmRSS.dcCategory + , dMkReport = mkKvmRSSReport + , dUse = useInstanceRSSData + } + -- * Collector choice -- | The list of Data Collectors used by hail and hbal. collectors :: Options -> [DataCollector] collectors opts | optIgnoreDynu opts = [] - | optMonDXen opts = [ xenCPUCollector ] - | otherwise = [ totalCPUCollector ] + | otherwise = + (if optMonDXen opts then [ xenCPUCollector ] else [ totalCPUCollector ] ) + ++ [ kvmRSSCollector | optMonDKvmRSS opts ] -- * Querying infrastructure -- 2.6.0.rc2.230.g3dd15c0
