1 {-| Cluster information printer.
7 Copyright (C) 2012 Google Inc.
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.
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.
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
26 module Ganeti.HTools.Program.Hinfo (main, options) where
33 import Text.Printf (printf)
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
41 import Ganeti.HTools.CLI
42 import Ganeti.HTools.ExtLoader
43 import Ganeti.HTools.Loader
46 -- | Options list and functions.
60 -- | Group information data-type.
61 data GroupInfo = GroupInfo { giName :: String
70 -- | Node group statistics.
71 calcGroupInfo :: Group.Group
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
82 score = Cluster.compCV nl
83 in GroupInfo (Group.name g) nl_size il_size bn_size bi_size n1h score
85 -- | Helper to format one group row result.
86 groupRowFormatHelper :: GroupInfo -> [String]
87 groupRowFormatHelper 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
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",
109 printf "Node group information:\n%s"
110 (printTable " " header grs [False, True, True, True, True,
113 printf "Cluster is N+1 %s\n" $ if cn1h then "happy" else "unhappy"
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
122 putStrLn "No split instances found"::IO ()
124 putStrLn "Found instances belonging to multiple node groups:"
125 mapM_ (\i -> hPutStrLn stderr $ " " ++ Instance.name i) split_insts
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 ()
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 ()
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
146 main :: Options -> [String] -> IO ()
148 unless (null args) $ do
149 hPutStrLn stderr "Error: this program doesn't take any arguments."
150 exitWith $ ExitFailure 1
152 let verbose = optVerbose opts
153 shownodes = optShowNodes opts
154 showinsts = optShowInsts opts
156 (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
158 putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
161 putStrLn $ "Loaded cluster ipolicy: " ++ show ipol
163 nlf <- setNodeStatus opts fixed_nl
165 commonInfo verbose gl nlf ilf
167 splitInstancesInfo verbose nlf ilf
169 showGroupInfo verbose gl nlf ilf
171 maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
173 maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
175 printf "Cluster coefficients:\n%s" (Cluster.printStats " " nlf)::IO ()
176 printf "Cluster score: %.8f\n" (Cluster.compCV nlf)