root / src / Ganeti / HTools / Program / Hcheck.hs @ 2d6bdcc5
History | View | Annotate | Download (11.6 kB)
1 | 22e513e7 | Agata Murawska | {-| Cluster checker. |
---|---|---|---|
2 | 22e513e7 | Agata Murawska | |
3 | 22e513e7 | Agata Murawska | -} |
4 | 22e513e7 | Agata Murawska | |
5 | 22e513e7 | Agata Murawska | {- |
6 | 22e513e7 | Agata Murawska | |
7 | bfa99f7a | Iustin Pop | Copyright (C) 2012, 2013 Google Inc. |
8 | 22e513e7 | Agata Murawska | |
9 | 22e513e7 | Agata Murawska | This program is free software; you can redistribute it and/or modify |
10 | 22e513e7 | Agata Murawska | it under the terms of the GNU General Public License as published by |
11 | 22e513e7 | Agata Murawska | the Free Software Foundation; either version 2 of the License, or |
12 | 22e513e7 | Agata Murawska | (at your option) any later version. |
13 | 22e513e7 | Agata Murawska | |
14 | 22e513e7 | Agata Murawska | This program is distributed in the hope that it will be useful, but |
15 | 22e513e7 | Agata Murawska | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | 22e513e7 | Agata Murawska | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | 22e513e7 | Agata Murawska | General Public License for more details. |
18 | 22e513e7 | Agata Murawska | |
19 | 22e513e7 | Agata Murawska | You should have received a copy of the GNU Gene52al Public License |
20 | 22e513e7 | Agata Murawska | along with this program; if not, write to the Free Software |
21 | 22e513e7 | Agata Murawska | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
22 | 22e513e7 | Agata Murawska | 02110-1301, USA. |
23 | 22e513e7 | Agata Murawska | |
24 | 22e513e7 | Agata Murawska | -} |
25 | 22e513e7 | Agata Murawska | |
26 | 22278fa7 | Iustin Pop | module Ganeti.HTools.Program.Hcheck |
27 | 22278fa7 | Iustin Pop | ( main |
28 | 22278fa7 | Iustin Pop | , options |
29 | 22278fa7 | Iustin Pop | , arguments |
30 | 22278fa7 | Iustin Pop | ) where |
31 | 22e513e7 | Agata Murawska | |
32 | 22e513e7 | Agata Murawska | import Control.Monad |
33 | 7568b296 | Iustin Pop | import Data.List (transpose) |
34 | 22e513e7 | Agata Murawska | import System.Exit |
35 | 1213f9d6 | Agata Murawska | import Text.Printf (printf) |
36 | 1213f9d6 | Agata Murawska | |
37 | 1213f9d6 | Agata Murawska | import qualified Ganeti.HTools.Container as Container |
38 | 1213f9d6 | Agata Murawska | import qualified Ganeti.HTools.Cluster as Cluster |
39 | 5cdbde9a | Agata Murawska | import qualified Ganeti.HTools.Group as Group |
40 | 1213f9d6 | Agata Murawska | import qualified Ganeti.HTools.Node as Node |
41 | 1213f9d6 | Agata Murawska | import qualified Ganeti.HTools.Instance as Instance |
42 | 1213f9d6 | Agata Murawska | |
43 | 1213f9d6 | Agata Murawska | import qualified Ganeti.HTools.Program.Hbal as Hbal |
44 | 22e513e7 | Agata Murawska | |
45 | 22278fa7 | Iustin Pop | import Ganeti.Common |
46 | 22e513e7 | Agata Murawska | import Ganeti.HTools.CLI |
47 | 1213f9d6 | Agata Murawska | import Ganeti.HTools.ExtLoader |
48 | 1213f9d6 | Agata Murawska | import Ganeti.HTools.Loader |
49 | 1213f9d6 | Agata Murawska | import Ganeti.HTools.Types |
50 | 707cd3d7 | Helga Velroyen | import Ganeti.Utils |
51 | 22e513e7 | Agata Murawska | |
52 | 22e513e7 | Agata Murawska | -- | Options list and functions. |
53 | d66aa238 | Iustin Pop | options :: IO [OptType] |
54 | 29a30533 | Iustin Pop | options = do |
55 | 29a30533 | Iustin Pop | luxi <- oLuxiSocket |
56 | d66aa238 | Iustin Pop | return |
57 | d66aa238 | Iustin Pop | [ oDataFile |
58 | d66aa238 | Iustin Pop | , oDiskMoves |
59 | d66aa238 | Iustin Pop | , oDynuFile |
60 | d66aa238 | Iustin Pop | , oEvacMode |
61 | d66aa238 | Iustin Pop | , oExInst |
62 | d66aa238 | Iustin Pop | , oExTags |
63 | d66aa238 | Iustin Pop | , oIAllocSrc |
64 | d66aa238 | Iustin Pop | , oInstMoves |
65 | 29a30533 | Iustin Pop | , luxi |
66 | d66aa238 | Iustin Pop | , oMachineReadable |
67 | d66aa238 | Iustin Pop | , oMaxCpu |
68 | d66aa238 | Iustin Pop | , oMaxSolLength |
69 | d66aa238 | Iustin Pop | , oMinDisk |
70 | d66aa238 | Iustin Pop | , oMinGain |
71 | d66aa238 | Iustin Pop | , oMinGainLim |
72 | d66aa238 | Iustin Pop | , oMinScore |
73 | d66aa238 | Iustin Pop | , oNoSimulation |
74 | d66aa238 | Iustin Pop | , oOfflineNode |
75 | d66aa238 | Iustin Pop | , oQuiet |
76 | d66aa238 | Iustin Pop | , oRapiMaster |
77 | d66aa238 | Iustin Pop | , oSelInst |
78 | d66aa238 | Iustin Pop | , oVerbose |
79 | d66aa238 | Iustin Pop | ] |
80 | 22e513e7 | Agata Murawska | |
81 | 22278fa7 | Iustin Pop | -- | The list of arguments supported by the program. |
82 | 22278fa7 | Iustin Pop | arguments :: [ArgCompletion] |
83 | 22278fa7 | Iustin Pop | arguments = [] |
84 | 22278fa7 | Iustin Pop | |
85 | 1213f9d6 | Agata Murawska | -- | Check phase - are we before (initial) or after rebalance. |
86 | 1213f9d6 | Agata Murawska | data Phase = Initial |
87 | 1213f9d6 | Agata Murawska | | Rebalanced |
88 | 1213f9d6 | Agata Murawska | |
89 | 22b16dd0 | Agata Murawska | -- | Level of presented statistics. |
90 | f6b9c6e5 | Iustin Pop | data Level = GroupLvl String -- ^ Group level, with name |
91 | f6b9c6e5 | Iustin Pop | | ClusterLvl -- ^ Cluster level |
92 | 22b16dd0 | Agata Murawska | |
93 | 7f119c27 | Iustin Pop | -- | A type alias for a group index and node\/instance lists. |
94 | 7f119c27 | Iustin Pop | type GroupInfo = (Gdx, (Node.List, Instance.List)) |
95 | 7f119c27 | Iustin Pop | |
96 | 7f119c27 | Iustin Pop | -- | A type alias for group stats. |
97 | 7f119c27 | Iustin Pop | type GroupStats = ((Group.Group, Double), [Int]) |
98 | 7f119c27 | Iustin Pop | |
99 | d64acbb5 | Agata Murawska | -- | Prefix for machine readable names. |
100 | 1213f9d6 | Agata Murawska | htcPrefix :: String |
101 | 1213f9d6 | Agata Murawska | htcPrefix = "HCHECK" |
102 | 1213f9d6 | Agata Murawska | |
103 | 1213f9d6 | Agata Murawska | -- | Data showed both per group and per cluster. |
104 | 1213f9d6 | Agata Murawska | commonData :: [(String, String)] |
105 | 1213f9d6 | Agata Murawska | commonData =[ ("N1_FAIL", "Nodes not N+1 happy") |
106 | 1213f9d6 | Agata Murawska | , ("CONFLICT_TAGS", "Nodes with conflicting instances") |
107 | 85890a9d | Iustin Pop | , ("OFFLINE_PRI", "Instances having the primary node offline") |
108 | 85890a9d | Iustin Pop | , ("OFFLINE_SEC", "Instances having a secondary node offline") |
109 | 1213f9d6 | Agata Murawska | ] |
110 | 1213f9d6 | Agata Murawska | |
111 | 1213f9d6 | Agata Murawska | -- | Data showed per group. |
112 | 1213f9d6 | Agata Murawska | groupData :: [(String, String)] |
113 | 1213f9d6 | Agata Murawska | groupData = commonData ++ [("SCORE", "Group score")] |
114 | 1213f9d6 | Agata Murawska | |
115 | 1213f9d6 | Agata Murawska | -- | Data showed per cluster. |
116 | 1213f9d6 | Agata Murawska | clusterData :: [(String, String)] |
117 | 92eacdd8 | Agata Murawska | clusterData = commonData ++ |
118 | b1a9d630 | Iustin Pop | [ ("NEED_REBALANCE", "Cluster is not healthy") ] |
119 | 92eacdd8 | Agata Murawska | |
120 | b5b19d5e | Agata Murawska | -- | Phase-specific prefix for machine readable version. |
121 | b5b19d5e | Agata Murawska | phasePrefix :: Phase -> String |
122 | b5b19d5e | Agata Murawska | phasePrefix Initial = "INIT" |
123 | b5b19d5e | Agata Murawska | phasePrefix Rebalanced = "FINAL" |
124 | b5b19d5e | Agata Murawska | |
125 | b5b19d5e | Agata Murawska | -- | Level-specific prefix for machine readable version. |
126 | b5b19d5e | Agata Murawska | levelPrefix :: Level -> String |
127 | f6b9c6e5 | Iustin Pop | levelPrefix GroupLvl {} = "GROUP" |
128 | f6b9c6e5 | Iustin Pop | levelPrefix ClusterLvl = "CLUSTER" |
129 | b5b19d5e | Agata Murawska | |
130 | 3c0687b5 | Agata Murawska | -- | Machine-readable keys to show depending on given level. |
131 | 3c0687b5 | Agata Murawska | keysData :: Level -> [String] |
132 | f6b9c6e5 | Iustin Pop | keysData GroupLvl {} = map fst groupData |
133 | f6b9c6e5 | Iustin Pop | keysData ClusterLvl = map fst clusterData |
134 | 3c0687b5 | Agata Murawska | |
135 | b5b19d5e | Agata Murawska | -- | Description of phases for human readable version. |
136 | b5b19d5e | Agata Murawska | phaseDescr :: Phase -> String |
137 | b5b19d5e | Agata Murawska | phaseDescr Initial = "initially" |
138 | b5b19d5e | Agata Murawska | phaseDescr Rebalanced = "after rebalancing" |
139 | b5b19d5e | Agata Murawska | |
140 | 3c0687b5 | Agata Murawska | -- | Description to show depending on given level. |
141 | 3c0687b5 | Agata Murawska | descrData :: Level -> [String] |
142 | f6b9c6e5 | Iustin Pop | descrData GroupLvl {} = map snd groupData |
143 | f6b9c6e5 | Iustin Pop | descrData ClusterLvl = map snd clusterData |
144 | 3c0687b5 | Agata Murawska | |
145 | 3c0687b5 | Agata Murawska | -- | Human readable prefix for statistics. |
146 | f6b9c6e5 | Iustin Pop | phaseLevelDescr :: Phase -> Level -> String |
147 | f6b9c6e5 | Iustin Pop | phaseLevelDescr phase (GroupLvl name) = |
148 | 3c0687b5 | Agata Murawska | printf "Statistics for group %s %s\n" name $ phaseDescr phase |
149 | f6b9c6e5 | Iustin Pop | phaseLevelDescr phase ClusterLvl = |
150 | 3c0687b5 | Agata Murawska | printf "Cluster statistics %s\n" $ phaseDescr phase |
151 | 1213f9d6 | Agata Murawska | |
152 | 22b16dd0 | Agata Murawska | -- | Format a list of key, value as a shell fragment. |
153 | 22b16dd0 | Agata Murawska | printKeysHTC :: [(String, String)] -> IO () |
154 | 22b16dd0 | Agata Murawska | printKeysHTC = printKeys htcPrefix |
155 | 22b16dd0 | Agata Murawska | |
156 | 92eacdd8 | Agata Murawska | -- | Prepare string from boolean value. |
157 | 92eacdd8 | Agata Murawska | printBool :: Bool -- ^ Whether the result should be machine readable |
158 | 92eacdd8 | Agata Murawska | -> Bool -- ^ Value to be converted to string |
159 | 92eacdd8 | Agata Murawska | -> String |
160 | 92eacdd8 | Agata Murawska | printBool True True = "1" |
161 | 92eacdd8 | Agata Murawska | printBool True False = "0" |
162 | 92eacdd8 | Agata Murawska | printBool False b = show b |
163 | 92eacdd8 | Agata Murawska | |
164 | 81bcbbd3 | Iustin Pop | -- | Print mapping from group idx to group uuid (only in machine |
165 | 81bcbbd3 | Iustin Pop | -- readable mode). |
166 | 592601b3 | Agata Murawska | printGroupsMappings :: Group.List -> IO () |
167 | 592601b3 | Agata Murawska | printGroupsMappings gl = do |
168 | 5b11f8db | Iustin Pop | let extract_vals g = (printf "GROUP_UUID_%d" $ Group.idx g :: String, |
169 | 5b11f8db | Iustin Pop | Group.uuid g) |
170 | 592601b3 | Agata Murawska | printpairs = map extract_vals (Container.elems gl) |
171 | 592601b3 | Agata Murawska | printKeysHTC printpairs |
172 | 592601b3 | Agata Murawska | |
173 | 3c0687b5 | Agata Murawska | -- | Prepare a single key given a certain level and phase of simulation. |
174 | f6b9c6e5 | Iustin Pop | prepareKey :: Level -> Phase -> String -> String |
175 | f6b9c6e5 | Iustin Pop | prepareKey level@ClusterLvl phase suffix = |
176 | 3c0687b5 | Agata Murawska | printf "%s_%s_%s" (phasePrefix phase) (levelPrefix level) suffix |
177 | f6b9c6e5 | Iustin Pop | prepareKey level@(GroupLvl idx) phase suffix = |
178 | 3c0687b5 | Agata Murawska | printf "%s_%s_%s_%s" (phasePrefix phase) (levelPrefix level) idx suffix |
179 | 3c0687b5 | Agata Murawska | |
180 | 3c0687b5 | Agata Murawska | -- | Print all the statistics for given level and phase. |
181 | 3c0687b5 | Agata Murawska | printStats :: Int -- ^ Verbosity level |
182 | 3c0687b5 | Agata Murawska | -> Bool -- ^ If the output should be machine readable |
183 | 3c0687b5 | Agata Murawska | -> Level -- ^ Level on which we are printing |
184 | 3c0687b5 | Agata Murawska | -> Phase -- ^ Current phase of simulation |
185 | 3c0687b5 | Agata Murawska | -> [String] -- ^ Values to print |
186 | 3c0687b5 | Agata Murawska | -> IO () |
187 | f6b9c6e5 | Iustin Pop | printStats _ True level phase values = do |
188 | f6b9c6e5 | Iustin Pop | let keys = map (prepareKey level phase) (keysData level) |
189 | 3c0687b5 | Agata Murawska | printKeysHTC $ zip keys values |
190 | 3c0687b5 | Agata Murawska | |
191 | f6b9c6e5 | Iustin Pop | printStats verbose False level phase values = do |
192 | f6b9c6e5 | Iustin Pop | let prefix = phaseLevelDescr phase level |
193 | 3c0687b5 | Agata Murawska | descr = descrData level |
194 | bfa99f7a | Iustin Pop | unless (verbose < 1) $ do |
195 | 4b77c2a2 | Iustin Pop | putStrLn "" |
196 | 4b77c2a2 | Iustin Pop | putStr prefix |
197 | 2cdaf225 | Iustin Pop | mapM_ (uncurry (printf " %s: %s\n")) (zip descr values) |
198 | 3c0687b5 | Agata Murawska | |
199 | 3c0687b5 | Agata Murawska | -- | Extract name or idx from group. |
200 | 3c0687b5 | Agata Murawska | extractGroupData :: Bool -> Group.Group -> String |
201 | 81bcbbd3 | Iustin Pop | extractGroupData True grp = show $ Group.idx grp |
202 | 3c0687b5 | Agata Murawska | extractGroupData False grp = Group.name grp |
203 | 3c0687b5 | Agata Murawska | |
204 | 3c0687b5 | Agata Murawska | -- | Prepare values for group. |
205 | 3c0687b5 | Agata Murawska | prepareGroupValues :: [Int] -> Double -> [String] |
206 | 3c0687b5 | Agata Murawska | prepareGroupValues stats score = |
207 | 81bcbbd3 | Iustin Pop | map show stats ++ [printf "%.8f" score] |
208 | 3c0687b5 | Agata Murawska | |
209 | 3c0687b5 | Agata Murawska | -- | Prepare values for cluster. |
210 | 3c0687b5 | Agata Murawska | prepareClusterValues :: Bool -> [Int] -> [Bool] -> [String] |
211 | 3c0687b5 | Agata Murawska | prepareClusterValues machineread stats bstats = |
212 | 81bcbbd3 | Iustin Pop | map show stats ++ map (printBool machineread) bstats |
213 | 3c0687b5 | Agata Murawska | |
214 | 3c0687b5 | Agata Murawska | -- | Print all the statistics on a group level. |
215 | 7f119c27 | Iustin Pop | printGroupStats :: Int -> Bool -> Phase -> GroupStats -> IO () |
216 | 4b77c2a2 | Iustin Pop | printGroupStats verbose machineread phase ((grp, score), stats) = do |
217 | 3c0687b5 | Agata Murawska | let values = prepareGroupValues stats score |
218 | 3c0687b5 | Agata Murawska | extradata = extractGroupData machineread grp |
219 | f6b9c6e5 | Iustin Pop | printStats verbose machineread (GroupLvl extradata) phase values |
220 | 1213f9d6 | Agata Murawska | |
221 | 1213f9d6 | Agata Murawska | -- | Print all the statistics on a cluster (global) level. |
222 | b1a9d630 | Iustin Pop | printClusterStats :: Int -> Bool -> Phase -> [Int] -> Bool -> IO () |
223 | b1a9d630 | Iustin Pop | printClusterStats verbose machineread phase stats needhbal = do |
224 | b1a9d630 | Iustin Pop | let values = prepareClusterValues machineread stats [needhbal] |
225 | f6b9c6e5 | Iustin Pop | printStats verbose machineread ClusterLvl phase values |
226 | caa97388 | Agata Murawska | |
227 | caa97388 | Agata Murawska | -- | Check if any of cluster metrics is non-zero. |
228 | caa97388 | Agata Murawska | clusterNeedsRebalance :: [Int] -> Bool |
229 | caa97388 | Agata Murawska | clusterNeedsRebalance stats = sum stats > 0 |
230 | 1213f9d6 | Agata Murawska | |
231 | 1213f9d6 | Agata Murawska | {- | Check group for N+1 hapiness, conflicts of primaries on nodes and |
232 | 1213f9d6 | Agata Murawska | instances residing on offline nodes. |
233 | 1213f9d6 | Agata Murawska | |
234 | 1213f9d6 | Agata Murawska | -} |
235 | 7f119c27 | Iustin Pop | perGroupChecks :: Group.List -> GroupInfo -> GroupStats |
236 | 4b77c2a2 | Iustin Pop | perGroupChecks gl (gidx, (nl, il)) = |
237 | 5cdbde9a | Agata Murawska | let grp = Container.find gidx gl |
238 | 5cdbde9a | Agata Murawska | offnl = filter Node.offline (Container.elems nl) |
239 | 2cdaf225 | Iustin Pop | n1violated = length . fst $ Cluster.computeBadItems nl il |
240 | 1213f9d6 | Agata Murawska | conflicttags = length $ filter (>0) |
241 | 1213f9d6 | Agata Murawska | (map Node.conflictingPrimaries (Container.elems nl)) |
242 | 1213f9d6 | Agata Murawska | offline_pri = sum . map length $ map Node.pList offnl |
243 | 1213f9d6 | Agata Murawska | offline_sec = length $ map Node.sList offnl |
244 | 1213f9d6 | Agata Murawska | score = Cluster.compCV nl |
245 | 1213f9d6 | Agata Murawska | groupstats = [ n1violated |
246 | 1213f9d6 | Agata Murawska | , conflicttags |
247 | 1213f9d6 | Agata Murawska | , offline_pri |
248 | 1213f9d6 | Agata Murawska | , offline_sec |
249 | 1213f9d6 | Agata Murawska | ] |
250 | 4b77c2a2 | Iustin Pop | in ((grp, score), groupstats) |
251 | 1213f9d6 | Agata Murawska | |
252 | 1213f9d6 | Agata Murawska | -- | Use Hbal's iterateDepth to simulate group rebalance. |
253 | 81bcbbd3 | Iustin Pop | executeSimulation :: Options -> Cluster.Table -> Double |
254 | 81bcbbd3 | Iustin Pop | -> Gdx -> Node.List -> Instance.List |
255 | 7f119c27 | Iustin Pop | -> IO GroupInfo |
256 | 5cc97485 | Agata Murawska | executeSimulation opts ini_tbl min_cv gidx nl il = do |
257 | 5cc97485 | Agata Murawska | let imlen = maximum . map (length . Instance.alias) $ Container.elems il |
258 | 5cc97485 | Agata Murawska | nmlen = maximum . map (length . Node.alias) $ Container.elems nl |
259 | 5cc97485 | Agata Murawska | |
260 | 5cc97485 | Agata Murawska | (fin_tbl, _) <- Hbal.iterateDepth False ini_tbl |
261 | 5cc97485 | Agata Murawska | (optMaxLength opts) |
262 | 5cc97485 | Agata Murawska | (optDiskMoves opts) |
263 | 5cc97485 | Agata Murawska | (optInstMoves opts) |
264 | 5cc97485 | Agata Murawska | nmlen imlen [] min_cv |
265 | 5cc97485 | Agata Murawska | (optMinGainLim opts) (optMinGain opts) |
266 | 5cc97485 | Agata Murawska | (optEvacMode opts) |
267 | 5cc97485 | Agata Murawska | |
268 | 5cc97485 | Agata Murawska | let (Cluster.Table fin_nl fin_il _ _) = fin_tbl |
269 | 5cc97485 | Agata Murawska | return (gidx, (fin_nl, fin_il)) |
270 | 5cc97485 | Agata Murawska | |
271 | 5cc97485 | Agata Murawska | -- | Simulate group rebalance if group's score is not good |
272 | 7f119c27 | Iustin Pop | maybeSimulateGroupRebalance :: Options -> GroupInfo -> IO GroupInfo |
273 | 5cc97485 | Agata Murawska | maybeSimulateGroupRebalance opts (gidx, (nl, il)) = do |
274 | 1213f9d6 | Agata Murawska | let ini_cv = Cluster.compCV nl |
275 | 1213f9d6 | Agata Murawska | ini_tbl = Cluster.Table nl il ini_cv [] |
276 | 1213f9d6 | Agata Murawska | min_cv = optMinScore opts |
277 | 81bcbbd3 | Iustin Pop | if ini_cv < min_cv |
278 | 1213f9d6 | Agata Murawska | then return (gidx, (nl, il)) |
279 | 5cc97485 | Agata Murawska | else executeSimulation opts ini_tbl min_cv gidx nl il |
280 | 1213f9d6 | Agata Murawska | |
281 | ecc39665 | Agata Murawska | -- | Decide whether to simulate rebalance. |
282 | ecc39665 | Agata Murawska | maybeSimulateRebalance :: Bool -- ^ Whether to simulate rebalance |
283 | ecc39665 | Agata Murawska | -> Options -- ^ Command line options |
284 | 7f119c27 | Iustin Pop | -> [GroupInfo] -- ^ Group data |
285 | 7f119c27 | Iustin Pop | -> IO [GroupInfo] |
286 | ecc39665 | Agata Murawska | maybeSimulateRebalance True opts cluster = |
287 | 5cc97485 | Agata Murawska | mapM (maybeSimulateGroupRebalance opts) cluster |
288 | ecc39665 | Agata Murawska | maybeSimulateRebalance False _ cluster = return cluster |
289 | ecc39665 | Agata Murawska | |
290 | 1213f9d6 | Agata Murawska | -- | Prints the final @OK@ marker in machine readable output. |
291 | 1213f9d6 | Agata Murawska | printFinalHTC :: Bool -> IO () |
292 | 1213f9d6 | Agata Murawska | printFinalHTC = printFinal htcPrefix |
293 | 1213f9d6 | Agata Murawska | |
294 | 22e513e7 | Agata Murawska | -- | Main function. |
295 | 22e513e7 | Agata Murawska | main :: Options -> [String] -> IO () |
296 | 1213f9d6 | Agata Murawska | main opts args = do |
297 | 707cd3d7 | Helga Velroyen | unless (null args) $ exitErr "This program doesn't take any arguments." |
298 | 1213f9d6 | Agata Murawska | |
299 | 1213f9d6 | Agata Murawska | let verbose = optVerbose opts |
300 | 1213f9d6 | Agata Murawska | machineread = optMachineReadable opts |
301 | 1213f9d6 | Agata Murawska | nosimulation = optNoSimulation opts |
302 | 1213f9d6 | Agata Murawska | |
303 | 5cdbde9a | Agata Murawska | (ClusterData gl fixed_nl ilf _ _) <- loadExternalData opts |
304 | 1213f9d6 | Agata Murawska | nlf <- setNodeStatus opts fixed_nl |
305 | 1213f9d6 | Agata Murawska | |
306 | b1a9d630 | Iustin Pop | let splitcluster = Cluster.splitCluster nlf ilf |
307 | 1213f9d6 | Agata Murawska | |
308 | 592601b3 | Agata Murawska | when machineread $ printGroupsMappings gl |
309 | 5cdbde9a | Agata Murawska | |
310 | 4b77c2a2 | Iustin Pop | let groupsstats = map (perGroupChecks gl) splitcluster |
311 | 4b77c2a2 | Iustin Pop | clusterstats = map sum . transpose . map snd $ groupsstats |
312 | caa97388 | Agata Murawska | needrebalance = clusterNeedsRebalance clusterstats |
313 | 1213f9d6 | Agata Murawska | |
314 | bfa99f7a | Iustin Pop | unless (verbose < 1 || machineread) . |
315 | 66ad857a | Iustin Pop | putStrLn $ if nosimulation |
316 | 66ad857a | Iustin Pop | then "Running in no-simulation mode." |
317 | 66ad857a | Iustin Pop | else if needrebalance |
318 | 66ad857a | Iustin Pop | then "Cluster needs rebalancing." |
319 | 66ad857a | Iustin Pop | else "No need to rebalance cluster, no problems found." |
320 | 4b77c2a2 | Iustin Pop | |
321 | 4b77c2a2 | Iustin Pop | mapM_ (printGroupStats verbose machineread Initial) groupsstats |
322 | 1213f9d6 | Agata Murawska | |
323 | 4b77c2a2 | Iustin Pop | printClusterStats verbose machineread Initial clusterstats needrebalance |
324 | 1213f9d6 | Agata Murawska | |
325 | ecc39665 | Agata Murawska | let exitOK = nosimulation || not needrebalance |
326 | b1a9d630 | Iustin Pop | simulate = not nosimulation && needrebalance |
327 | ecc39665 | Agata Murawska | |
328 | ecc39665 | Agata Murawska | rebalancedcluster <- maybeSimulateRebalance simulate opts splitcluster |
329 | ecc39665 | Agata Murawska | |
330 | ecc39665 | Agata Murawska | when (simulate || machineread) $ do |
331 | 4b77c2a2 | Iustin Pop | let newgroupstats = map (perGroupChecks gl) rebalancedcluster |
332 | 4b77c2a2 | Iustin Pop | newclusterstats = map sum . transpose . map snd $ newgroupstats |
333 | caa97388 | Agata Murawska | newneedrebalance = clusterNeedsRebalance clusterstats |
334 | ecc39665 | Agata Murawska | |
335 | 4b77c2a2 | Iustin Pop | mapM_ (printGroupStats verbose machineread Rebalanced) newgroupstats |
336 | 4b77c2a2 | Iustin Pop | |
337 | caa97388 | Agata Murawska | printClusterStats verbose machineread Rebalanced newclusterstats |
338 | b1a9d630 | Iustin Pop | newneedrebalance |
339 | 1213f9d6 | Agata Murawska | |
340 | 1213f9d6 | Agata Murawska | printFinalHTC machineread |
341 | ecc39665 | Agata Murawska | |
342 | 2cdaf225 | Iustin Pop | unless exitOK . exitWith $ ExitFailure 1 |