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