Revision 375969eb htools/Ganeti/HTools/Program/Hspace.hs
b/htools/Ganeti/HTools/Program/Hspace.hs | ||
---|---|---|
63 | 63 |
, oIMem |
64 | 64 |
, oIDisk |
65 | 65 |
, oIVcpus |
66 |
, oMachineReadable |
|
66 | 67 |
, oMaxCpu |
67 | 68 |
, oMinDisk |
68 | 69 |
, oTieredSpec |
... | ... | |
77 | 78 |
| PFinal |
78 | 79 |
| PTiered |
79 | 80 |
|
81 |
-- | The kind of instance spec we print. |
|
82 |
data SpecType = SpecNormal |
|
83 |
| SpecTiered |
|
84 |
|
|
85 |
-- | What we prefix a spec with. |
|
86 |
specPrefix :: SpecType -> String |
|
87 |
specPrefix SpecNormal = "SPEC" |
|
88 |
specPrefix SpecTiered = "TSPEC_INI" |
|
89 |
|
|
90 |
-- | The description of a spec. |
|
91 |
specDescription :: SpecType -> String |
|
92 |
specDescription SpecNormal = "Normal (fixed-size)" |
|
93 |
specDescription SpecTiered = "Tiered (initial size)" |
|
94 |
|
|
95 |
-- | Efficiency generic function. |
|
96 |
effFn :: (Cluster.CStats -> Integer) |
|
97 |
-> (Cluster.CStats -> Double) |
|
98 |
-> (Cluster.CStats -> Double) |
|
99 |
effFn fi ft cs = fromIntegral (fi cs) / ft cs |
|
100 |
|
|
101 |
-- | Memory efficiency. |
|
102 |
memEff :: Cluster.CStats -> Double |
|
103 |
memEff = effFn Cluster.csImem Cluster.csTmem |
|
104 |
|
|
105 |
-- | Disk efficiency. |
|
106 |
dskEff :: Cluster.CStats -> Double |
|
107 |
dskEff = effFn Cluster.csIdsk Cluster.csTdsk |
|
108 |
|
|
109 |
-- | Cpu efficiency. |
|
110 |
cpuEff :: Cluster.CStats -> Double |
|
111 |
cpuEff = effFn Cluster.csIcpu (fromIntegral . Cluster.csVcpu) |
|
112 |
|
|
80 | 113 |
statsData :: [(String, Cluster.CStats -> String)] |
81 | 114 |
statsData = [ ("SCORE", printf "%.8f" . Cluster.csScore) |
82 | 115 |
, ("INST_CNT", printf "%d" . Cluster.csNinst) |
... | ... | |
87 | 120 |
, ("MEM_INST", printf "%d" . Cluster.csImem) |
88 | 121 |
, ("MEM_OVERHEAD", |
89 | 122 |
\cs -> printf "%d" (Cluster.csXmem cs + Cluster.csNmem cs)) |
90 |
, ("MEM_EFF", |
|
91 |
\cs -> printf "%.8f" (fromIntegral (Cluster.csImem cs) / |
|
92 |
Cluster.csTmem cs)) |
|
123 |
, ("MEM_EFF", printf "%.8f" . memEff) |
|
93 | 124 |
, ("DSK_FREE", printf "%d" . Cluster.csFdsk) |
94 | 125 |
, ("DSK_AVAIL", printf "%d". Cluster.csAdsk) |
95 | 126 |
, ("DSK_RESVD", |
96 | 127 |
\cs -> printf "%d" (Cluster.csFdsk cs - Cluster.csAdsk cs)) |
97 | 128 |
, ("DSK_INST", printf "%d" . Cluster.csIdsk) |
98 |
, ("DSK_EFF", |
|
99 |
\cs -> printf "%.8f" (fromIntegral (Cluster.csIdsk cs) / |
|
100 |
Cluster.csTdsk cs)) |
|
129 |
, ("DSK_EFF", printf "%.8f" . dskEff) |
|
101 | 130 |
, ("CPU_INST", printf "%d" . Cluster.csIcpu) |
102 |
, ("CPU_EFF", |
|
103 |
\cs -> printf "%.8f" (fromIntegral (Cluster.csIcpu cs) / |
|
104 |
Cluster.csTcpu cs)) |
|
131 |
, ("CPU_EFF", printf "%.8f" . cpuEff) |
|
105 | 132 |
, ("MNODE_MEM_AVAIL", printf "%d" . Cluster.csMmem) |
106 | 133 |
, ("MNODE_DSK_AVAIL", printf "%d" . Cluster.csMdsk) |
107 | 134 |
] |
... | ... | |
128 | 155 |
PFinal -> "FIN" |
129 | 156 |
PTiered -> "TRL" |
130 | 157 |
|
131 |
-- | Print final stats and related metrics |
|
132 |
printResults :: Node.List -> Int -> Int -> [(FailMode, Int)] -> IO () |
|
133 |
printResults fin_nl num_instances allocs sreason = do |
|
158 |
-- | Print final stats and related metrics. |
|
159 |
printResults :: Bool -> Node.List -> Node.List -> Int -> Int |
|
160 |
-> [(FailMode, Int)] -> IO () |
|
161 |
printResults True _ fin_nl num_instances allocs sreason = do |
|
134 | 162 |
let fin_stats = Cluster.totalResources fin_nl |
135 | 163 |
fin_instances = num_instances + allocs |
136 | 164 |
|
... | ... | |
150 | 178 |
] |
151 | 179 |
printKeys $ map (\(x, y) -> (printf "ALLOC_%s_CNT" (show x), |
152 | 180 |
printf "%d" y)) sreason |
181 |
|
|
182 |
printResults False ini_nl fin_nl _ allocs sreason = do |
|
183 |
putStrLn "Normal (fixed-size) allocation results:" |
|
184 |
printf " - %3d instances allocated\n" allocs :: IO () |
|
185 |
printf " - most likely failure reason: %s\n" $ failureReason sreason::IO () |
|
186 |
printClusterScores ini_nl fin_nl |
|
187 |
printClusterEff (Cluster.totalResources fin_nl) |
|
188 |
|
|
189 |
-- | Prints the final @OK@ marker in machine readable output. |
|
190 |
printFinal :: Bool -> IO () |
|
191 |
printFinal True = |
|
153 | 192 |
-- this should be the final entry |
154 | 193 |
printKeys [("OK", "1")] |
155 | 194 |
|
195 |
printFinal False = return () |
|
196 |
|
|
156 | 197 |
-- | Compute the tiered spec counts from a list of allocated |
157 | 198 |
-- instances. |
158 | 199 |
tieredSpecMap :: [Instance.Instance] |
... | ... | |
222 | 263 |
-- strings, whereas the rest are numeric |
223 | 264 |
[False, False, False, True, True, True] |
224 | 265 |
|
266 |
-- | Formats nicely a list of resources. |
|
267 |
formatResources :: a -> [(String, (a->String))] -> String |
|
268 |
formatResources res = |
|
269 |
intercalate ", " . map (\(a, fn) -> a ++ " " ++ fn res) |
|
270 |
|
|
271 |
-- | Print the cluster resources. |
|
272 |
printCluster :: Bool -> Cluster.CStats -> Int -> IO () |
|
273 |
printCluster True ini_stats node_count = do |
|
274 |
printKeys $ map (\(a, fn) -> ("CLUSTER_" ++ a, fn ini_stats)) clusterData |
|
275 |
printKeys [("CLUSTER_NODES", printf "%d" node_count)] |
|
276 |
printKeys $ printStats PInitial ini_stats |
|
277 |
|
|
278 |
printCluster False ini_stats node_count = do |
|
279 |
printf "The cluster has %d nodes and the following resources:\n %s.\n" |
|
280 |
node_count (formatResources ini_stats clusterData)::IO () |
|
281 |
printf "There are %s initial instances on the cluster.\n" |
|
282 |
(if inst_count > 0 then show inst_count else "no" ) |
|
283 |
where inst_count = Cluster.csNinst ini_stats |
|
284 |
|
|
285 |
-- | Prints the normal instance spec. |
|
286 |
printISpec :: Bool -> RSpec -> SpecType -> DiskTemplate -> IO () |
|
287 |
printISpec True ispec spec disk_template = do |
|
288 |
printKeys $ map (\(a, fn) -> (prefix ++ "_" ++ a, fn ispec)) specData |
|
289 |
printKeys [ (prefix ++ "_RQN", printf "%d" req_nodes) ] |
|
290 |
printKeys [ (prefix ++ "_DISK_TEMPLATE", dtToString disk_template) ] |
|
291 |
where req_nodes = Instance.requiredNodes disk_template |
|
292 |
prefix = specPrefix spec |
|
293 |
|
|
294 |
printISpec False ispec spec disk_template = do |
|
295 |
printf "%s instance spec is:\n %s, using disk\ |
|
296 |
\ template '%s'.\n" |
|
297 |
(specDescription spec) |
|
298 |
(formatResources ispec specData) (dtToString disk_template) |
|
299 |
|
|
300 |
-- | Prints the tiered results. |
|
301 |
printTiered :: Bool -> [(RSpec, Int)] -> Double |
|
302 |
-> Node.List -> Node.List -> [(FailMode, Int)] -> IO () |
|
303 |
printTiered True spec_map m_cpu nl trl_nl _ = do |
|
304 |
printKeys $ printStats PTiered (Cluster.totalResources trl_nl) |
|
305 |
printKeys [("TSPEC", intercalate " " (formatSpecMap spec_map))] |
|
306 |
printAllocationStats m_cpu nl trl_nl |
|
307 |
|
|
308 |
printTiered False spec_map _ ini_nl fin_nl sreason = do |
|
309 |
_ <- printf "Tiered allocation results:\n" |
|
310 |
mapM_ (\(ispec, cnt) -> |
|
311 |
printf " - %3d instances of spec %s\n" cnt |
|
312 |
(formatResources ispec specData)) spec_map |
|
313 |
printf " - most likely failure reason: %s\n" $ failureReason sreason::IO () |
|
314 |
printClusterScores ini_nl fin_nl |
|
315 |
printClusterEff (Cluster.totalResources fin_nl) |
|
316 |
|
|
317 |
printClusterScores :: Node.List -> Node.List -> IO () |
|
318 |
printClusterScores ini_nl fin_nl = do |
|
319 |
printf " - initial cluster score: %.8f\n" $ Cluster.compCV ini_nl::IO () |
|
320 |
printf " - final cluster score: %.8f\n" $ Cluster.compCV fin_nl |
|
321 |
|
|
322 |
printClusterEff :: Cluster.CStats -> IO () |
|
323 |
printClusterEff cs = |
|
324 |
mapM_ (\(s, fn) -> |
|
325 |
printf " - %s usage efficiency: %5.2f%%\n" s (fn cs * 100)) |
|
326 |
[("memory", memEff), |
|
327 |
(" disk", dskEff), |
|
328 |
(" vcpu", cpuEff)] |
|
329 |
|
|
330 |
-- | Computes the most likely failure reason. |
|
331 |
failureReason :: [(FailMode, Int)] -> String |
|
332 |
failureReason = show . fst . head |
|
333 |
|
|
334 |
-- | Sorts the failure reasons. |
|
335 |
sortReasons :: [(FailMode, Int)] -> [(FailMode, Int)] |
|
336 |
sortReasons = reverse . sortBy (comparing snd) |
|
337 |
|
|
225 | 338 |
-- | Main function. |
226 | 339 |
main :: IO () |
227 | 340 |
main = do |
... | ... | |
237 | 350 |
shownodes = optShowNodes opts |
238 | 351 |
disk_template = optDiskTemplate opts |
239 | 352 |
req_nodes = Instance.requiredNodes disk_template |
353 |
machine_r = optMachineReadable opts |
|
240 | 354 |
|
241 | 355 |
(ClusterData gl fixed_nl il ctags) <- loadExternalData opts |
242 | 356 |
|
243 |
printKeys $ map (\(a, fn) -> ("SPEC_" ++ a, fn ispec)) specData |
|
244 |
printKeys [ ("SPEC_RQN", printf "%d" req_nodes) ] |
|
245 |
printKeys [ ("SPEC_DISK_TEMPLATE", dtToString disk_template) ] |
|
246 |
|
|
247 | 357 |
let num_instances = length $ Container.elems il |
248 | 358 |
|
249 | 359 |
let offline_passed = optOffline opts |
... | ... | |
289 | 399 |
hPrintf stderr "Initial coefficients: overall %.8f, %s\n" |
290 | 400 |
ini_cv (Cluster.printStats nl) |
291 | 401 |
|
292 |
printKeys $ map (\(a, fn) -> ("CLUSTER_" ++ a, fn ini_stats)) clusterData
|
|
293 |
printKeys [("CLUSTER_NODES", printf "%d" (length all_nodes))] |
|
294 |
printKeys $ printStats PInitial ini_stats
|
|
402 |
printCluster machine_r ini_stats (length all_nodes)
|
|
403 |
|
|
404 |
printISpec machine_r ispec SpecNormal disk_template
|
|
295 | 405 |
|
296 | 406 |
let bad_nodes = fst $ Cluster.computeBadItems nl il |
297 | 407 |
stop_allocation = length bad_nodes > 0 |
... | ... | |
316 | 426 |
(case optTieredSpec opts of |
317 | 427 |
Nothing -> return () |
318 | 428 |
Just tspec -> do |
319 |
(_, trl_nl, trl_il, trl_ixes, _) <-
|
|
429 |
(treason, trl_nl, trl_il, trl_ixes, _) <-
|
|
320 | 430 |
if stop_allocation |
321 | 431 |
then return result_noalloc |
322 | 432 |
else exitifbad (Cluster.tieredAlloc nl il Nothing (iofspec tspec) |
323 | 433 |
allocnodes [] []) |
324 | 434 |
let spec_map' = tieredSpecMap trl_ixes |
435 |
treason' = sortReasons treason |
|
325 | 436 |
|
326 | 437 |
printAllocationMap verbose "Tiered allocation map" trl_nl trl_ixes |
327 | 438 |
|
... | ... | |
331 | 442 |
maybeSaveData (optSaveCluster opts) "tiered" "after tiered allocation" |
332 | 443 |
(ClusterData gl trl_nl trl_il ctags) |
333 | 444 |
|
334 |
printKeys $ map (\(a, fn) -> ("TSPEC_INI_" ++ a, fn tspec)) specData
|
|
335 |
printKeys $ printStats PTiered (Cluster.totalResources trl_nl) |
|
336 |
printKeys [("TSPEC", intercalate " " (formatSpecMap spec_map'))]
|
|
337 |
printAllocationStats m_cpu nl trl_nl)
|
|
445 |
printISpec machine_r tspec SpecTiered disk_template
|
|
446 |
|
|
447 |
printTiered machine_r spec_map' m_cpu nl trl_nl treason'
|
|
448 |
) |
|
338 | 449 |
|
339 | 450 |
-- Run the standard (avg-mode) allocation |
340 | 451 |
|
... | ... | |
345 | 456 |
reqinst allocnodes [] []) |
346 | 457 |
|
347 | 458 |
let allocs = length ixes |
348 |
sreason = reverse $ sortBy (comparing snd) ereason
|
|
459 |
sreason = sortReasons ereason
|
|
349 | 460 |
|
350 | 461 |
printAllocationMap verbose "Standard allocation map" fin_nl ixes |
351 | 462 |
|
... | ... | |
354 | 465 |
maybeSaveData (optSaveCluster opts) "alloc" "after standard allocation" |
355 | 466 |
(ClusterData gl fin_nl fin_il ctags) |
356 | 467 |
|
357 |
printResults fin_nl num_instances allocs sreason |
|
468 |
printResults machine_r nl fin_nl num_instances allocs sreason |
|
469 |
|
|
470 |
printFinal machine_r |
Also available in: Unified diff