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