Revision 2922d2c5
b/Makefile.am | ||
---|---|---|
347 | 347 |
doc/walkthrough.rst |
348 | 348 |
|
349 | 349 |
HS_PROGS = htools/htools |
350 |
HS_BIN_ROLES = hbal hscan hspace |
|
350 |
HS_BIN_ROLES = hbal hscan hspace hinfo
|
|
351 | 351 |
|
352 | 352 |
HS_ALL_PROGS = $(HS_PROGS) htools/test |
353 | 353 |
HS_PROG_SRCS = $(patsubst %,%.hs,$(HS_ALL_PROGS)) |
... | ... | |
389 | 389 |
htools/Ganeti/HTools/Program.hs \ |
390 | 390 |
htools/Ganeti/HTools/Program/Hail.hs \ |
391 | 391 |
htools/Ganeti/HTools/Program/Hbal.hs \ |
392 |
htools/Ganeti/HTools/Program/Hinfo.hs \ |
|
392 | 393 |
htools/Ganeti/HTools/Program/Hscan.hs \ |
393 | 394 |
htools/Ganeti/HTools/Program/Hspace.hs \ |
394 | 395 |
htools/Ganeti/BasicTypes.hs \ |
b/htools/Ganeti/HTools/Cluster.hs | ||
---|---|---|
1330 | 1330 |
formatTable (header:map helper sil) isnum |
1331 | 1331 |
|
1332 | 1332 |
-- | Shows statistics for a given node list. |
1333 |
printStats :: Node.List -> String |
|
1334 |
printStats nl = |
|
1333 |
printStats :: String -> Node.List -> String
|
|
1334 |
printStats lp nl =
|
|
1335 | 1335 |
let dcvs = compDetailedCV $ Container.elems nl |
1336 | 1336 |
(weights, names) = unzip detailedCVInfo |
1337 | 1337 |
hd = zip3 (weights ++ repeat 1) (names ++ repeat "unknown") dcvs |
1338 |
formatted = map (\(w, header, val) -> |
|
1339 |
printf "%s=%.8f(x%.2f)" header val w::String) hd |
|
1340 |
in intercalate ", " formatted |
|
1338 |
header = [ "Field", "Value", "Weight" ] |
|
1339 |
formatted = map (\(w, h, val) -> |
|
1340 |
[ h |
|
1341 |
, printf "%.8f" val |
|
1342 |
, printf "x%.2f" w |
|
1343 |
]) hd |
|
1344 |
in unlines . map ((++) lp) . map ((:) ' ' . unwords) $ |
|
1345 |
formatTable (header:formatted) $ False:repeat True |
|
1341 | 1346 |
|
1342 | 1347 |
-- | Convert a placement into a list of OpCodes (basically a job). |
1343 | 1348 |
iMoveToJob :: Node.List -- ^ The node list; only used for node |
b/htools/Ganeti/HTools/Program.hs | ||
---|---|---|
33 | 33 |
import qualified Ganeti.HTools.Program.Hbal as Hbal |
34 | 34 |
import qualified Ganeti.HTools.Program.Hscan as Hscan |
35 | 35 |
import qualified Ganeti.HTools.Program.Hspace as Hspace |
36 |
import qualified Ganeti.HTools.Program.Hinfo as Hinfo |
|
36 | 37 |
|
37 | 38 |
-- | Supported binaries. |
38 | 39 |
personalities :: [(String, (Options -> [String] -> IO (), [OptType]))] |
... | ... | |
40 | 41 |
, ("hbal", (Hbal.main, Hbal.options)) |
41 | 42 |
, ("hscan", (Hscan.main, Hscan.options)) |
42 | 43 |
, ("hspace", (Hspace.main, Hspace.options)) |
44 |
, ("hinfo", (Hinfo.main, Hinfo.options)) |
|
43 | 45 |
] |
b/htools/Ganeti/HTools/Program/Hbal.hs | ||
---|---|---|
373 | 373 |
checkNeedRebalance opts ini_cv |
374 | 374 |
|
375 | 375 |
if verbose > 2 |
376 |
then printf "Initial coefficients: overall %.8f, %s\n"
|
|
377 |
ini_cv (Cluster.printStats nl)::IO () |
|
376 |
then printf "Initial coefficients: overall %.8f\n%s"
|
|
377 |
ini_cv (Cluster.printStats " " nl)::IO ()
|
|
378 | 378 |
else printf "Initial score: %.8f\n" ini_cv |
379 | 379 |
|
380 | 380 |
putStrLn "Trying to minimize the CV..." |
... | ... | |
392 | 392 |
sol_msg = case () of |
393 | 393 |
_ | null fin_plc -> printf "No solution found\n" |
394 | 394 |
| verbose > 2 -> |
395 |
printf "Final coefficients: overall %.8f, %s\n"
|
|
396 |
fin_cv (Cluster.printStats fin_nl) |
|
395 |
printf "Final coefficients: overall %.8f\n%s"
|
|
396 |
fin_cv (Cluster.printStats " " fin_nl)
|
|
397 | 397 |
| otherwise -> |
398 | 398 |
printf "Cluster score improved from %.8f to %.8f\n" |
399 | 399 |
ini_cv fin_cv ::String |
b/htools/Ganeti/HTools/Program/Hinfo.hs | ||
---|---|---|
1 |
{-| Cluster information printer. |
|
2 |
|
|
3 |
-} |
|
4 |
|
|
5 |
{- |
|
6 |
|
|
7 |
Copyright (C) 2012 Google Inc. |
|
8 |
|
|
9 |
This program is free software; you can redistribute it and/or modify |
|
10 |
it under the terms of the GNU General Public License as published by |
|
11 |
the Free Software Foundation; either version 2 of the License, or |
|
12 |
(at your option) any later version. |
|
13 |
|
|
14 |
This program is distributed in the hope that it will be useful, but |
|
15 |
WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
17 |
General Public License for more details. |
|
18 |
|
|
19 |
You should have received a copy of the GNU General Public License |
|
20 |
along with this program; if not, write to the Free Software |
|
21 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
|
22 |
02110-1301, USA. |
|
23 |
|
|
24 |
-} |
|
25 |
|
|
26 |
module Ganeti.HTools.Program.Hinfo (main, options) where |
|
27 |
|
|
28 |
import Control.Monad |
|
29 |
import Data.List |
|
30 |
import System.Exit |
|
31 |
import System.IO |
|
32 |
|
|
33 |
import Text.Printf (printf) |
|
34 |
|
|
35 |
import qualified Ganeti.HTools.Container as Container |
|
36 |
import qualified Ganeti.HTools.Cluster as Cluster |
|
37 |
import qualified Ganeti.HTools.Node as Node |
|
38 |
import qualified Ganeti.HTools.Instance as Instance |
|
39 |
|
|
40 |
import Ganeti.HTools.CLI |
|
41 |
import Ganeti.HTools.ExtLoader |
|
42 |
import Ganeti.HTools.Loader |
|
43 |
|
|
44 |
-- | Options list and functions. |
|
45 |
options :: [OptType] |
|
46 |
options = |
|
47 |
[ oPrintNodes |
|
48 |
, oPrintInsts |
|
49 |
, oDataFile |
|
50 |
, oRapiMaster |
|
51 |
, oLuxiSocket |
|
52 |
, oVerbose |
|
53 |
, oQuiet |
|
54 |
, oOfflineNode |
|
55 |
, oShowVer |
|
56 |
, oShowHelp |
|
57 |
] |
|
58 |
|
|
59 |
-- | Do a few checks on the cluster data. |
|
60 |
checkCluster :: Int -> Node.List -> Instance.List -> IO () |
|
61 |
checkCluster verbose nl il = do |
|
62 |
-- nothing to do on an empty cluster |
|
63 |
when (Container.null il) $ do |
|
64 |
printf "Cluster is empty, exiting.\n"::IO () |
|
65 |
exitWith ExitSuccess |
|
66 |
|
|
67 |
-- hbal doesn't currently handle split clusters |
|
68 |
let split_insts = Cluster.findSplitInstances nl il |
|
69 |
unless (null split_insts) $ do |
|
70 |
hPutStrLn stderr "Found instances belonging to multiple node groups:" |
|
71 |
mapM_ (\i -> hPutStrLn stderr $ " " ++ Instance.name i) split_insts |
|
72 |
hPutStrLn stderr "Aborting." |
|
73 |
exitWith $ ExitFailure 1 |
|
74 |
|
|
75 |
printf "Loaded %d nodes, %d instances\n" |
|
76 |
(Container.size nl) |
|
77 |
(Container.size il)::IO () |
|
78 |
|
|
79 |
let csf = commonSuffix nl il |
|
80 |
when (not (null csf) && verbose > 1) $ |
|
81 |
printf "Note: Stripping common suffix of '%s' from names\n" csf |
|
82 |
|
|
83 |
-- | Main function. |
|
84 |
main :: Options -> [String] -> IO () |
|
85 |
main opts args = do |
|
86 |
unless (null args) $ do |
|
87 |
hPutStrLn stderr "Error: this program doesn't take any arguments." |
|
88 |
exitWith $ ExitFailure 1 |
|
89 |
|
|
90 |
let verbose = optVerbose opts |
|
91 |
shownodes = optShowNodes opts |
|
92 |
showinsts = optShowInsts opts |
|
93 |
|
|
94 |
(ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts |
|
95 |
|
|
96 |
when (verbose > 1) $ do |
|
97 |
putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags |
|
98 |
putStrLn $ "Loaded cluster ipolicy: " ++ show ipol |
|
99 |
putStrLn $ "Loaded node groups: " ++ show gl |
|
100 |
|
|
101 |
nlf <- setNodeStatus opts fixed_nl |
|
102 |
checkCluster verbose nlf ilf |
|
103 |
|
|
104 |
printf "Cluster has %d node group(s)\n" (Container.size gl)::IO () |
|
105 |
|
|
106 |
maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf) |
|
107 |
|
|
108 |
maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf) |
|
109 |
|
|
110 |
printf "Cluster coefficients:\n%s" (Cluster.printStats " " nlf)::IO () |
|
111 |
printf "Cluster score: %.8f\n" (Cluster.compCV nlf) |
b/htools/Ganeti/HTools/Program/Hspace.hs | ||
---|---|---|
424 | 424 |
maybePrintNodes (optShowNodes opts) "Initial cluster" (Cluster.printNodes nl) |
425 | 425 |
|
426 | 426 |
when (verbose > 2) $ |
427 |
hPrintf stderr "Initial coefficients: overall %.8f, %s\n"
|
|
428 |
(Cluster.compCV nl) (Cluster.printStats nl) |
|
427 |
hPrintf stderr "Initial coefficients: overall %.8f\n%s"
|
|
428 |
(Cluster.compCV nl) (Cluster.printStats " " nl)
|
|
429 | 429 |
|
430 | 430 |
printCluster machine_r (Cluster.totalResources nl) (length all_nodes) |
431 | 431 |
|
Also available in: Unified diff