Statistics
| Branch: | Tag: | Revision:

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

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
    ]
67

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
173
  nlf <- setNodeStatus opts fixed_nl
174

    
175
  commonInfo verbose gl nlf ilf
176

    
177
  splitInstancesInfo verbose nlf ilf
178

    
179
  showGroupInfo verbose gl nlf ilf
180

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

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

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