Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (5.2 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
  , oVerbose
55
  , oQuiet
56
  , oOfflineNode
57
  , oShowVer
58
  , oShowHelp
59
  ]
60

    
61
-- | Node group statistics.
62
calcGroupInfo :: Group.Group
63
              -> Node.List
64
              -> Instance.List
65
              -> (String, (Int, Int), (Int, Int), Bool)
66
calcGroupInfo g nl il =
67
  let nl_size                    = Container.size nl
68
      il_size                    = Container.size il
69
      (bad_nodes, bad_instances) = Cluster.computeBadItems nl il
70
      bn_size                    = length bad_nodes
71
      bi_size                    = length bad_instances
72
      n1h                        = bn_size == 0
73
  in (Group.name g, (nl_size, il_size), (bn_size, bi_size), n1h)
74

    
75
-- | Helper to format one group row result.
76
groupRowFormatHelper :: (String, (Int, Int), (Int, Int), Bool) -> [String]
77
groupRowFormatHelper (gname, (nl_size, il_size), (bn_size, bi_size), n1h) =
78
  [ gname
79
  , printf "%d" nl_size
80
  , printf "%d" il_size
81
  , printf "%d" bn_size
82
  , printf "%d" bi_size
83
  , show n1h ]
84

    
85
-- | Print node group information.
86
showGroupInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
87
showGroupInfo verbose gl nl il = do
88
  let cgrs   = map (\(gdx, (gnl, gil)) ->
89
                 calcGroupInfo (Container.find gdx gl) gnl gil) $
90
                 Cluster.splitCluster nl il
91
      cn1h   = all (\(_, _, _, n1h) -> n1h) cgrs
92
      grs    = map groupRowFormatHelper cgrs
93
      header = ["Group", "Nodes", "Instances", "Bad_Nodes", "Bad_Instances",
94
                "N+1"]
95

    
96
  when (verbose > 1) $
97
    printf "Node group information:\n%s"
98
           (printTable "  " header grs [False, True, True, True, True, False])
99

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

    
102
-- | Gather and print split instances.
103
splitInstancesInfo :: Int -> Node.List -> Instance.List -> IO ()
104
splitInstancesInfo verbose nl il = do
105
  let split_insts = Cluster.findSplitInstances nl il
106
  if (null split_insts)
107
    then
108
      when (verbose > 1) $ do
109
        putStrLn "No split instances found"::IO ()
110
    else do
111
      putStrLn "Found instances belonging to multiple node groups:"
112
      mapM_ (\i -> hPutStrLn stderr $ "  " ++ Instance.name i) split_insts
113

    
114
-- | Print common (interesting) information.
115
commonInfo :: Int -> Group.List -> Node.List -> Instance.List -> IO ()
116
commonInfo verbose gl nl il = do
117
  when (Container.null il && verbose > 1) $ do
118
         printf "Cluster is empty.\n"::IO ()
119

    
120
  let nl_size = (Container.size nl)
121
      il_size = (Container.size il)
122
      gl_size = (Container.size gl)
123
  printf "Loaded %d %s, %d %s, %d %s\n"
124
             nl_size (plural nl_size "node" "nodes")
125
             il_size (plural il_size "instance" "instances")
126
             gl_size (plural gl_size "node group" "node groups")::IO ()
127

    
128
  let csf = commonSuffix nl il
129
  when (not (null csf) && verbose > 1) $
130
       printf "Note: Stripping common suffix of '%s' from names\n" csf
131

    
132
-- | Main function.
133
main :: Options -> [String] -> IO ()
134
main opts args = do
135
  unless (null args) $ do
136
         hPutStrLn stderr "Error: this program doesn't take any arguments."
137
         exitWith $ ExitFailure 1
138

    
139
  let verbose = optVerbose opts
140
      shownodes = optShowNodes opts
141
      showinsts = optShowInsts opts
142

    
143
  (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
144

    
145
  when (verbose > 1) $ do
146
       putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
147
       putStrLn $ "Loaded cluster ipolicy: " ++ show ipol
148
       putStrLn $ "Loaded node groups: " ++ show gl
149

    
150
  nlf <- setNodeStatus opts fixed_nl
151

    
152
  commonInfo verbose gl nlf ilf
153

    
154
  splitInstancesInfo verbose nlf ilf
155

    
156
  showGroupInfo verbose gl nlf ilf
157

    
158
  maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
159

    
160
  maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
161

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