Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / HTools / Program / Hinfo.hs @ c62bec27

History | View | Annotate | Download (5.7 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
27
  ( main
28
  , options
29
  , arguments
30
  ) where
31

    
32
import Control.Monad
33
import Data.List
34
import System.IO
35

    
36
import Text.Printf (printf)
37

    
38
import qualified Ganeti.HTools.Container as Container
39
import qualified Ganeti.HTools.Cluster as Cluster
40
import qualified Ganeti.HTools.Node as Node
41
import qualified Ganeti.HTools.Group as Group
42
import qualified Ganeti.HTools.Instance as Instance
43

    
44
import Ganeti.Common
45
import Ganeti.HTools.CLI
46
import Ganeti.HTools.ExtLoader
47
import Ganeti.HTools.Loader
48
import Ganeti.Utils
49

    
50
-- | Options list and functions.
51
options :: IO [OptType]
52
options = do
53
  luxi <- oLuxiSocket
54
  return
55
    [ oPrintNodes
56
    , oPrintInsts
57
    , oDataFile
58
    , oRapiMaster
59
    , luxi
60
    , oIAllocSrc
61
    , oVerbose
62
    , oQuiet
63
    , oOfflineNode
64
    , oIgnoreDyn
65
    , oMonD
66
    , oMonDDataFile
67
    ]
68

    
69
-- | The list of arguments supported by the program.
70
arguments :: [ArgCompletion]
71
arguments = []
72

    
73
-- | Group information data-type.
74
data GroupInfo = GroupInfo { giName      :: String
75
                           , giNodeCount :: Int
76
                           , giInstCount :: Int
77
                           , giBadNodes  :: Int
78
                           , giBadInsts  :: Int
79
                           , giN1Status  :: Bool
80
                           , giScore     :: Double
81
                           }
82

    
83
-- | Node group statistics.
84
calcGroupInfo :: Group.Group
85
              -> Node.List
86
              -> Instance.List
87
              -> GroupInfo
88
calcGroupInfo g nl il =
89
  let nl_size                    = Container.size nl
90
      il_size                    = Container.size il
91
      (bad_nodes, bad_instances) = Cluster.computeBadItems nl il
92
      bn_size                    = length bad_nodes
93
      bi_size                    = length bad_instances
94
      n1h                        = bn_size == 0
95
      score                      = Cluster.compCV nl
96
  in GroupInfo (Group.name g) nl_size il_size bn_size bi_size n1h score
97

    
98
-- | Helper to format one group row result.
99
groupRowFormatHelper :: GroupInfo -> [String]
100
groupRowFormatHelper gi =
101
  [ giName gi
102
  , printf "%d" $ giNodeCount gi
103
  , printf "%d" $ giInstCount gi
104
  , printf "%d" $ giBadNodes gi
105
  , printf "%d" $ giBadInsts gi
106
  , show $ giN1Status gi
107
  , printf "%.8f" $ giScore gi
108
  ]
109

    
110
-- | Print node group information.
111
showGroupInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
112
showGroupInfo verbose gl nl il = do
113
  let cgrs   = map (\(gdx, (gnl, gil)) ->
114
                 calcGroupInfo (Container.find gdx gl) gnl gil) $
115
                 Cluster.splitCluster nl il
116
      cn1h   = all giN1Status cgrs
117
      grs    = map groupRowFormatHelper cgrs
118
      header = ["Group", "Nodes", "Instances", "Bad_Nodes", "Bad_Instances",
119
                "N+1", "Score"]
120

    
121
  when (verbose > 1) $
122
    printf "Node group information:\n%s"
123
           (printTable "  " header grs [False, True, True, True, True,
124
                                        False, True])
125

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

    
128
-- | Gather and print split instances.
129
splitInstancesInfo :: Int -> Node.List -> Instance.List -> IO ()
130
splitInstancesInfo verbose nl il = do
131
  let split_insts = Cluster.findSplitInstances nl il
132
  if null split_insts
133
    then
134
      when (verbose > 1) $
135
        putStrLn "No split instances found"::IO ()
136
    else do
137
      putStrLn "Found instances belonging to multiple node groups:"
138
      mapM_ (\i -> hPutStrLn stderr $ "  " ++ Instance.name i) split_insts
139

    
140
-- | Print common (interesting) information.
141
commonInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
142
commonInfo verbose gl nl il = do
143
  when (Container.null il && verbose > 1) $
144
    printf "Cluster is empty.\n"::IO ()
145

    
146
  let nl_size = Container.size nl
147
      il_size = Container.size il
148
      gl_size = Container.size gl
149
  printf "Loaded %d %s, %d %s, %d %s\n"
150
             nl_size (plural nl_size "node" "nodes")
151
             il_size (plural il_size "instance" "instances")
152
             gl_size (plural gl_size "node group" "node groups")::IO ()
153

    
154
  let csf = commonSuffix nl il
155
  when (not (null csf) && verbose > 2) $
156
       printf "Note: Stripping common suffix of '%s' from names\n" csf
157

    
158
-- | Main function.
159
main :: Options -> [String] -> IO ()
160
main opts args = do
161
  unless (null args) $ exitErr "This program doesn't take any arguments."
162

    
163
  let verbose = optVerbose opts
164
      shownodes = optShowNodes opts
165
      showinsts = optShowInsts opts
166

    
167
  (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
168

    
169
  putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
170

    
171
  when (verbose > 2) .
172
       putStrLn $ "Loaded cluster ipolicy: " ++ show ipol
173

    
174
  nlf <- setNodeStatus opts fixed_nl
175

    
176
  commonInfo verbose gl nlf ilf
177

    
178
  splitInstancesInfo verbose nlf ilf
179

    
180
  showGroupInfo verbose gl nlf ilf
181

    
182
  maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
183

    
184
  maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
185

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