Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / Program / Hinfo.hs @ d1da5a45

History | View | Annotate | Download (5.6 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
-- | Group information data-type.
63
data GroupInfo = GroupInfo { giName      :: String
64
                           , giNodeCount :: Int
65
                           , giInstCount :: Int
66
                           , giBadNodes  :: Int
67
                           , giBadInsts  :: Int
68
                           , giN1Status  :: Bool
69
                           , giScore     :: Double
70
                           }
71

    
72
-- | Node group statistics.
73
calcGroupInfo :: Group.Group
74
              -> Node.List
75
              -> Instance.List
76
              -> GroupInfo
77
calcGroupInfo g nl il =
78
  let nl_size                    = Container.size nl
79
      il_size                    = Container.size il
80
      (bad_nodes, bad_instances) = Cluster.computeBadItems nl il
81
      bn_size                    = length bad_nodes
82
      bi_size                    = length bad_instances
83
      n1h                        = bn_size == 0
84
      score                      = Cluster.compCV nl
85
  in GroupInfo (Group.name g) nl_size il_size bn_size bi_size n1h score
86

    
87
-- | Helper to format one group row result.
88
groupRowFormatHelper :: GroupInfo -> [String]
89
groupRowFormatHelper gi =
90
  [ giName gi
91
  , printf "%d" $ giNodeCount gi
92
  , printf "%d" $ giInstCount gi
93
  , printf "%d" $ giBadNodes gi
94
  , printf "%d" $ giBadInsts gi
95
  , show $ giN1Status gi
96
  , printf "%.8f" $ giScore gi
97
  ]
98

    
99
-- | Print node group information.
100
showGroupInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
101
showGroupInfo verbose gl nl il = do
102
  let cgrs   = map (\(gdx, (gnl, gil)) ->
103
                 calcGroupInfo (Container.find gdx gl) gnl gil) $
104
                 Cluster.splitCluster nl il
105
      cn1h   = all giN1Status cgrs
106
      grs    = map groupRowFormatHelper cgrs
107
      header = ["Group", "Nodes", "Instances", "Bad_Nodes", "Bad_Instances",
108
                "N+1", "Score"]
109

    
110
  when (verbose > 1) $
111
    printf "Node group information:\n%s"
112
           (printTable "  " header grs [False, True, True, True, True,
113
                                        False, True])
114

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

    
117
-- | Gather and print split instances.
118
splitInstancesInfo :: Int -> Node.List -> Instance.List -> IO ()
119
splitInstancesInfo verbose nl il = do
120
  let split_insts = Cluster.findSplitInstances nl il
121
  if null split_insts
122
    then
123
      when (verbose > 1) $
124
        putStrLn "No split instances found"::IO ()
125
    else do
126
      putStrLn "Found instances belonging to multiple node groups:"
127
      mapM_ (\i -> hPutStrLn stderr $ "  " ++ Instance.name i) split_insts
128

    
129
-- | Print common (interesting) information.
130
commonInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
131
commonInfo verbose gl nl il = do
132
  when (Container.null il && verbose > 1) $
133
    printf "Cluster is empty.\n"::IO ()
134

    
135
  let nl_size = Container.size nl
136
      il_size = Container.size il
137
      gl_size = Container.size gl
138
  printf "Loaded %d %s, %d %s, %d %s\n"
139
             nl_size (plural nl_size "node" "nodes")
140
             il_size (plural il_size "instance" "instances")
141
             gl_size (plural gl_size "node group" "node groups")::IO ()
142

    
143
  let csf = commonSuffix nl il
144
  when (not (null csf) && verbose > 2) $
145
       printf "Note: Stripping common suffix of '%s' from names\n" csf
146

    
147
-- | Main function.
148
main :: Options -> [String] -> IO ()
149
main opts args = do
150
  unless (null args) $ do
151
         hPutStrLn stderr "Error: this program doesn't take any arguments."
152
         exitWith $ ExitFailure 1
153

    
154
  let verbose = optVerbose opts
155
      shownodes = optShowNodes opts
156
      showinsts = optShowInsts opts
157

    
158
  (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
159

    
160
  putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
161

    
162
  when (verbose > 2) .
163
       putStrLn $ "Loaded cluster ipolicy: " ++ show ipol
164

    
165
  nlf <- setNodeStatus opts fixed_nl
166

    
167
  commonInfo verbose gl nlf ilf
168

    
169
  splitInstancesInfo verbose nlf ilf
170

    
171
  showGroupInfo verbose gl nlf ilf
172

    
173
  maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
174

    
175
  maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
176

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