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
36 import Text.Printf (printf)
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
45 import Ganeti.HTools.CLI
46 import Ganeti.HTools.ExtLoader
47 import Ganeti.HTools.Loader
50 -- | Options list and functions.
51 options :: IO [OptType]
66 -- | The list of arguments supported by the program.
67 arguments :: [ArgCompletion]
70 -- | Group information data-type.
71 data GroupInfo = GroupInfo { giName :: String
80 -- | Node group statistics.
81 calcGroupInfo :: Group.Group
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
92 score = Cluster.compCV nl
93 in GroupInfo (Group.name g) nl_size il_size bn_size bi_size n1h score
95 -- | Helper to format one group row result.
96 groupRowFormatHelper :: GroupInfo -> [String]
97 groupRowFormatHelper 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
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",
119 printf "Node group information:\n%s"
120 (printTable " " header grs [False, True, True, True, True,
123 printf "Cluster is N+1 %s\n" $ if cn1h then "happy" else "unhappy"
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
132 putStrLn "No split instances found"::IO ()
134 putStrLn "Found instances belonging to multiple node groups:"
135 mapM_ (\i -> hPutStrLn stderr $ " " ++ Instance.name i) split_insts
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 ()
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 ()
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
156 main :: Options -> [String] -> IO ()
158 unless (null args) $ exitErr "This program doesn't take any arguments."
160 let verbose = optVerbose opts
161 shownodes = optShowNodes opts
162 showinsts = optShowInsts opts
164 (ClusterData gl fixed_nl ilf ctags ipol) <- loadExternalData opts
166 putStrLn $ "Loaded cluster tags: " ++ intercalate "," ctags
169 putStrLn $ "Loaded cluster ipolicy: " ++ show ipol
171 nlf <- setNodeStatus opts fixed_nl
173 commonInfo verbose gl nlf ilf
175 splitInstancesInfo verbose nlf ilf
177 showGroupInfo verbose gl nlf ilf
179 maybePrintInsts showinsts "Instances" (Cluster.printInsts nlf ilf)
181 maybePrintNodes shownodes "Cluster" (Cluster.printNodes nlf)
183 printf "Cluster coefficients:\n%s" (Cluster.printStats " " nlf)::IO ()
184 printf "Cluster score: %.8f\n" (Cluster.compCV nlf)