Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / Program / Hinfo.hs @ 26d62e4c

History | View | Annotate | Download (5.5 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.CLI
42
import Ganeti.HTools.ExtLoader
43
import Ganeti.HTools.Loader
44
import Ganeti.Utils
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
  ]
59

    
60
-- | Group information data-type.
61
data GroupInfo = GroupInfo { giName      :: String
62
                           , giNodeCount :: Int
63
                           , giInstCount :: Int
64
                           , giBadNodes  :: Int
65
                           , giBadInsts  :: Int
66
                           , giN1Status  :: Bool
67
                           , giScore     :: Double
68
                           }
69

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

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

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

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

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

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

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

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

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

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

    
152
  let verbose = optVerbose opts
153
      shownodes = optShowNodes opts
154
      showinsts = optShowInsts opts
155

    
156
  (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
157

    
158
  putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
159

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

    
163
  nlf <- setNodeStatus opts fixed_nl
164

    
165
  commonInfo verbose gl nlf ilf
166

    
167
  splitInstancesInfo verbose nlf ilf
168

    
169
  showGroupInfo verbose gl nlf ilf
170

    
171
  maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
172

    
173
  maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
174

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