What about big pages?
Anyway, I would prefer to make 256 a literal constant.
Rest, LGTM.
On 10/19/2015 03:57 PM, 'Klaus Aehlig' via ganeti-devel wrote:
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