Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / HTools / Program / Hinfo.hs @ 3add7574

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

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

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

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

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

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

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

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

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

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

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

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

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

    
160
  let verbose = optVerbose opts
161
      shownodes = optShowNodes opts
162
      showinsts = optShowInsts opts
163

    
164
  (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
165

    
166
  putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
167

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

    
171
  nlf <- setNodeStatus opts fixed_nl
172

    
173
  commonInfo verbose gl nlf ilf
174

    
175
  splitInstancesInfo verbose nlf ilf
176

    
177
  showGroupInfo verbose gl nlf ilf
178

    
179
  maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
180

    
181
  maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
182

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