Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / Program / Hinfo.hs @ 5b11f8db

History | View | Annotate | Download (5.1 kB)

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.Group as Group
39
import qualified Ganeti.HTools.Instance as Instance
40

    
41
import Ganeti.HTools.Utils
42
import Ganeti.HTools.CLI
43
import Ganeti.HTools.ExtLoader
44
import Ganeti.HTools.Loader
45

    
46
-- | Options list and functions.
47
options :: [OptType]
48
options =
49
  [ oPrintNodes
50
  , oPrintInsts
51
  , oDataFile
52
  , oRapiMaster
53
  , oLuxiSocket
54
  , oIAllocSrc
55
  , oVerbose
56
  , oQuiet
57
  , oOfflineNode
58
  , oShowVer
59
  , oShowHelp
60
  ]
61

    
62
-- | Node group statistics.
63
calcGroupInfo :: Group.Group
64
              -> Node.List
65
              -> Instance.List
66
              -> (String, (Int, Int), (Int, Int), Bool)
67
calcGroupInfo g nl il =
68
  let nl_size                    = Container.size nl
69
      il_size                    = Container.size il
70
      (bad_nodes, bad_instances) = Cluster.computeBadItems nl il
71
      bn_size                    = length bad_nodes
72
      bi_size                    = length bad_instances
73
      n1h                        = bn_size == 0
74
  in (Group.name g, (nl_size, il_size), (bn_size, bi_size), n1h)
75

    
76
-- | Helper to format one group row result.
77
groupRowFormatHelper :: (String, (Int, Int), (Int, Int), Bool) -> [String]
78
groupRowFormatHelper (gname, (nl_size, il_size), (bn_size, bi_size), n1h) =
79
  [ gname
80
  , printf "%d" nl_size
81
  , printf "%d" il_size
82
  , printf "%d" bn_size
83
  , printf "%d" bi_size
84
  , show n1h ]
85

    
86
-- | Print node group information.
87
showGroupInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
88
showGroupInfo verbose gl nl il = do
89
  let cgrs   = map (\(gdx, (gnl, gil)) ->
90
                 calcGroupInfo (Container.find gdx gl) gnl gil) $
91
                 Cluster.splitCluster nl il
92
      cn1h   = all (\(_, _, _, n1h) -> n1h) cgrs
93
      grs    = map groupRowFormatHelper cgrs
94
      header = ["Group", "Nodes", "Instances", "Bad_Nodes", "Bad_Instances",
95
                "N+1"]
96

    
97
  when (verbose > 1) $
98
    printf "Node group information:\n%s"
99
           (printTable "  " header grs [False, True, True, True, True, False])
100

    
101
  printf "Cluster is N+1 %s\n" $ if cn1h then "happy" else "unhappy"
102

    
103
-- | Gather and print split instances.
104
splitInstancesInfo :: Int -> Node.List -> Instance.List -> IO ()
105
splitInstancesInfo verbose nl il = do
106
  let split_insts = Cluster.findSplitInstances nl il
107
  if null split_insts
108
    then
109
      when (verbose > 1) $
110
        putStrLn "No split instances found"::IO ()
111
    else do
112
      putStrLn "Found instances belonging to multiple node groups:"
113
      mapM_ (\i -> hPutStrLn stderr $ "  " ++ Instance.name i) split_insts
114

    
115
-- | Print common (interesting) information.
116
commonInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
117
commonInfo verbose gl nl il = do
118
  when (Container.null il && verbose > 1) $
119
    printf "Cluster is empty.\n"::IO ()
120

    
121
  let nl_size = Container.size nl
122
      il_size = Container.size il
123
      gl_size = Container.size gl
124
  printf "Loaded %d %s, %d %s, %d %s\n"
125
             nl_size (plural nl_size "node" "nodes")
126
             il_size (plural il_size "instance" "instances")
127
             gl_size (plural gl_size "node group" "node groups")::IO ()
128

    
129
  let csf = commonSuffix nl il
130
  when (not (null csf) && verbose > 2) $
131
       printf "Note: Stripping common suffix of '%s' from names\n" csf
132

    
133
-- | Main function.
134
main :: Options -> [String] -> IO ()
135
main opts args = do
136
  unless (null args) $ do
137
         hPutStrLn stderr "Error: this program doesn't take any arguments."
138
         exitWith $ ExitFailure 1
139

    
140
  let verbose = optVerbose opts
141
      shownodes = optShowNodes opts
142
      showinsts = optShowInsts opts
143

    
144
  (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
145

    
146
  putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
147

    
148
  when (verbose > 2) .
149
       putStrLn $ "Loaded cluster ipolicy: " ++ show ipol
150

    
151
  nlf <- setNodeStatus opts fixed_nl
152

    
153
  commonInfo verbose gl nlf ilf
154

    
155
  splitInstancesInfo verbose nlf ilf
156

    
157
  showGroupInfo verbose gl nlf ilf
158

    
159
  maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
160

    
161
  maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
162

    
163
  printf "Cluster coefficients:\n%s" (Cluster.printStats "  " nlf)::IO ()
164
  printf "Cluster score: %.8f\n" (Cluster.compCV nlf)