root / src / Ganeti / HTools / ExtLoader.hs @ 44ffd981
History | View | Annotate | Download (10.6 kB)
1 | c32c4e4d | Spyros Trigazis | {-# LANGUAGE BangPatterns #-} |
---|---|---|---|
2 | c32c4e4d | Spyros Trigazis | |
3 | 525bfb36 | Iustin Pop | {-| External data loader. |
4 | e8f89bb6 | Iustin Pop | |
5 | e8f89bb6 | Iustin Pop | This module holds the external data loading, and thus is the only one |
6 | cf924b6d | Iustin Pop | depending (via the specialized Text\/Rapi\/Luxi modules) on the actual |
7 | e8f89bb6 | Iustin Pop | libraries implementing the low-level protocols. |
8 | e8f89bb6 | Iustin Pop | |
9 | e8f89bb6 | Iustin Pop | -} |
10 | e8f89bb6 | Iustin Pop | |
11 | e8f89bb6 | Iustin Pop | {- |
12 | e8f89bb6 | Iustin Pop | |
13 | 88a10df5 | Iustin Pop | Copyright (C) 2009, 2010, 2011, 2012 Google Inc. |
14 | e8f89bb6 | Iustin Pop | |
15 | e8f89bb6 | Iustin Pop | This program is free software; you can redistribute it and/or modify |
16 | e8f89bb6 | Iustin Pop | it under the terms of the GNU General Public License as published by |
17 | e8f89bb6 | Iustin Pop | the Free Software Foundation; either version 2 of the License, or |
18 | e8f89bb6 | Iustin Pop | (at your option) any later version. |
19 | e8f89bb6 | Iustin Pop | |
20 | e8f89bb6 | Iustin Pop | This program is distributed in the hope that it will be useful, but |
21 | e8f89bb6 | Iustin Pop | WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | e8f89bb6 | Iustin Pop | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
23 | e8f89bb6 | Iustin Pop | General Public License for more details. |
24 | e8f89bb6 | Iustin Pop | |
25 | e8f89bb6 | Iustin Pop | You should have received a copy of the GNU General Public License |
26 | e8f89bb6 | Iustin Pop | along with this program; if not, write to the Free Software |
27 | e8f89bb6 | Iustin Pop | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
28 | e8f89bb6 | Iustin Pop | 02110-1301, USA. |
29 | e8f89bb6 | Iustin Pop | |
30 | e8f89bb6 | Iustin Pop | -} |
31 | e8f89bb6 | Iustin Pop | |
32 | e8f89bb6 | Iustin Pop | module Ganeti.HTools.ExtLoader |
33 | ebf38064 | Iustin Pop | ( loadExternalData |
34 | ebf38064 | Iustin Pop | , commonSuffix |
35 | ebf38064 | Iustin Pop | , maybeSaveData |
36 | c32c4e4d | Spyros Trigazis | , queryAllMonDDCs |
37 | 33ce4d2d | Spyros Trigazis | , pMonDData |
38 | ebf38064 | Iustin Pop | ) where |
39 | e8f89bb6 | Iustin Pop | |
40 | cc532bdd | Iustin Pop | import Control.Monad |
41 | 30d25dd8 | Iustin Pop | import Control.Exception |
42 | c32c4e4d | Spyros Trigazis | import Data.Maybe (isJust, fromJust, catMaybes) |
43 | c32c4e4d | Spyros Trigazis | import Network.Curl |
44 | 4188449c | Iustin Pop | import System.FilePath |
45 | e8f89bb6 | Iustin Pop | import System.IO |
46 | ef947a42 | Dato Simó | import System.Time (getClockTime) |
47 | 8cd36391 | Iustin Pop | import Text.Printf (hPrintf) |
48 | e8f89bb6 | Iustin Pop | |
49 | c32c4e4d | Spyros Trigazis | import qualified Text.JSON as J |
50 | c62bec27 | Spyros Trigazis | import qualified Data.Map as Map |
51 | c62bec27 | Spyros Trigazis | import qualified Data.List as L |
52 | c32c4e4d | Spyros Trigazis | |
53 | c32c4e4d | Spyros Trigazis | import qualified Ganeti.Constants as C |
54 | c32c4e4d | Spyros Trigazis | import qualified Ganeti.DataCollectors.CPUload as CPUload |
55 | c32c4e4d | Spyros Trigazis | import qualified Ganeti.HTools.Container as Container |
56 | 879d9290 | Iustin Pop | import qualified Ganeti.HTools.Backend.Luxi as Luxi |
57 | 879d9290 | Iustin Pop | import qualified Ganeti.HTools.Backend.Rapi as Rapi |
58 | 879d9290 | Iustin Pop | import qualified Ganeti.HTools.Backend.Simu as Simu |
59 | 879d9290 | Iustin Pop | import qualified Ganeti.HTools.Backend.Text as Text |
60 | 879d9290 | Iustin Pop | import qualified Ganeti.HTools.Backend.IAlloc as IAlloc |
61 | c32c4e4d | Spyros Trigazis | import qualified Ganeti.HTools.Node as Node |
62 | c32c4e4d | Spyros Trigazis | import qualified Ganeti.HTools.Instance as Instance |
63 | 017a0c3d | Iustin Pop | import Ganeti.HTools.Loader (mergeData, checkData, ClusterData(..) |
64 | 81b6fa23 | Klaus Aehlig | , commonSuffix, clearDynU) |
65 | e8f89bb6 | Iustin Pop | |
66 | 01e52493 | Iustin Pop | import Ganeti.BasicTypes |
67 | c32c4e4d | Spyros Trigazis | import Ganeti.Cpu.Types |
68 | c32c4e4d | Spyros Trigazis | import Ganeti.DataCollectors.Types |
69 | e8f89bb6 | Iustin Pop | import Ganeti.HTools.Types |
70 | e8f89bb6 | Iustin Pop | import Ganeti.HTools.CLI |
71 | c32c4e4d | Spyros Trigazis | import Ganeti.JSON |
72 | c32c4e4d | Spyros Trigazis | import Ganeti.Logging (logWarning) |
73 | 26d62e4c | Iustin Pop | import Ganeti.Utils (sepSplit, tryRead, exitIfBad, exitWhen) |
74 | e8f89bb6 | Iustin Pop | |
75 | 525bfb36 | Iustin Pop | -- | Error beautifier. |
76 | e8f89bb6 | Iustin Pop | wrapIO :: IO (Result a) -> IO (Result a) |
77 | 2cdaf225 | Iustin Pop | wrapIO = handle (\e -> return . Bad . show $ (e::IOException)) |
78 | e8f89bb6 | Iustin Pop | |
79 | 179c0828 | Iustin Pop | -- | Parses a user-supplied utilisation string. |
80 | aa8d2e71 | Iustin Pop | parseUtilisation :: String -> Result (String, DynUtil) |
81 | aa8d2e71 | Iustin Pop | parseUtilisation line = |
82 | ebf38064 | Iustin Pop | case sepSplit ' ' line of |
83 | ebf38064 | Iustin Pop | [name, cpu, mem, dsk, net] -> |
84 | ebf38064 | Iustin Pop | do |
85 | ebf38064 | Iustin Pop | rcpu <- tryRead name cpu |
86 | ebf38064 | Iustin Pop | rmem <- tryRead name mem |
87 | ebf38064 | Iustin Pop | rdsk <- tryRead name dsk |
88 | ebf38064 | Iustin Pop | rnet <- tryRead name net |
89 | ebf38064 | Iustin Pop | let du = DynUtil { cpuWeight = rcpu, memWeight = rmem |
90 | ebf38064 | Iustin Pop | , dskWeight = rdsk, netWeight = rnet } |
91 | ebf38064 | Iustin Pop | return (name, du) |
92 | ebf38064 | Iustin Pop | _ -> Bad $ "Cannot parse line " ++ line |
93 | aa8d2e71 | Iustin Pop | |
94 | e8f89bb6 | Iustin Pop | -- | External tool data loader from a variety of sources. |
95 | e8f89bb6 | Iustin Pop | loadExternalData :: Options |
96 | 017a0c3d | Iustin Pop | -> IO ClusterData |
97 | e8f89bb6 | Iustin Pop | loadExternalData opts = do |
98 | 16c2369c | Iustin Pop | let mhost = optMaster opts |
99 | e8f89bb6 | Iustin Pop | lsock = optLuxi opts |
100 | 16c2369c | Iustin Pop | tfile = optDataFile opts |
101 | e8f89bb6 | Iustin Pop | simdata = optNodeSim opts |
102 | 4892d955 | René Nussbaumer | iallocsrc = optIAllocSrc opts |
103 | e8f89bb6 | Iustin Pop | setRapi = mhost /= "" |
104 | e8f89bb6 | Iustin Pop | setLuxi = isJust lsock |
105 | 9983063b | Iustin Pop | setSim = (not . null) simdata |
106 | 16c2369c | Iustin Pop | setFile = isJust tfile |
107 | 4892d955 | René Nussbaumer | setIAllocSrc = isJust iallocsrc |
108 | 16c2369c | Iustin Pop | allSet = filter id [setRapi, setLuxi, setFile] |
109 | 0f15cc76 | Iustin Pop | exTags = case optExTags opts of |
110 | 0f15cc76 | Iustin Pop | Nothing -> [] |
111 | 0f15cc76 | Iustin Pop | Just etl -> map (++ ":") etl |
112 | 2d1708e0 | Guido Trotter | selInsts = optSelInst opts |
113 | 39f979b8 | Iustin Pop | exInsts = optExInst opts |
114 | 0f15cc76 | Iustin Pop | |
115 | 88a10df5 | Iustin Pop | exitWhen (length allSet > 1) "Only one of the rapi, luxi, and data\ |
116 | 707cd3d7 | Helga Velroyen | \ files options should be given." |
117 | e8f89bb6 | Iustin Pop | |
118 | 3603605a | Iustin Pop | util_contents <- maybe (return "") readFile (optDynuFile opts) |
119 | 88a10df5 | Iustin Pop | util_data <- exitIfBad "can't parse utilisation data" . |
120 | 88a10df5 | Iustin Pop | mapM parseUtilisation $ lines util_contents |
121 | e8f89bb6 | Iustin Pop | input_data <- |
122 | ebf38064 | Iustin Pop | case () of |
123 | ebf38064 | Iustin Pop | _ | setRapi -> wrapIO $ Rapi.loadData mhost |
124 | 2cdaf225 | Iustin Pop | | setLuxi -> wrapIO . Luxi.loadData $ fromJust lsock |
125 | ebf38064 | Iustin Pop | | setSim -> Simu.loadData simdata |
126 | 2cdaf225 | Iustin Pop | | setFile -> wrapIO . Text.loadData $ fromJust tfile |
127 | 2cdaf225 | Iustin Pop | | setIAllocSrc -> wrapIO . IAlloc.loadData $ fromJust iallocsrc |
128 | ebf38064 | Iustin Pop | | otherwise -> return $ Bad "No backend selected! Exiting." |
129 | ef947a42 | Dato Simó | now <- getClockTime |
130 | e8f89bb6 | Iustin Pop | |
131 | 81b6fa23 | Klaus Aehlig | let ignoreDynU = optIgnoreDynu opts |
132 | 81b6fa23 | Klaus Aehlig | eff_u = if ignoreDynU then [] else util_data |
133 | 81b6fa23 | Klaus Aehlig | ldresult = input_data >>= (if ignoreDynU then clearDynU else return) |
134 | 81b6fa23 | Klaus Aehlig | >>= mergeData eff_u exTags selInsts exInsts now |
135 | 88a10df5 | Iustin Pop | cdata <- exitIfBad "failed to load data, aborting" ldresult |
136 | c32c4e4d | Spyros Trigazis | cdata' <- if optMonD opts then queryAllMonDDCs cdata opts else return cdata |
137 | c32c4e4d | Spyros Trigazis | let (fix_msgs, nl) = checkData (cdNodes cdata') (cdInstances cdata') |
138 | e8f89bb6 | Iustin Pop | |
139 | 8cd36391 | Iustin Pop | unless (optVerbose opts == 0) $ maybeShowWarnings fix_msgs |
140 | e8f89bb6 | Iustin Pop | |
141 | c32c4e4d | Spyros Trigazis | return cdata' {cdNodes = nl} |
142 | 4188449c | Iustin Pop | |
143 | 4188449c | Iustin Pop | -- | Function to save the cluster data to a file. |
144 | 4188449c | Iustin Pop | maybeSaveData :: Maybe FilePath -- ^ The file prefix to save to |
145 | 4188449c | Iustin Pop | -> String -- ^ The suffix (extension) to add |
146 | 4188449c | Iustin Pop | -> String -- ^ Informational message |
147 | 4188449c | Iustin Pop | -> ClusterData -- ^ The cluster data |
148 | 4188449c | Iustin Pop | -> IO () |
149 | 4188449c | Iustin Pop | maybeSaveData Nothing _ _ _ = return () |
150 | 4188449c | Iustin Pop | maybeSaveData (Just path) ext msg cdata = do |
151 | 4188449c | Iustin Pop | let adata = Text.serializeCluster cdata |
152 | 4188449c | Iustin Pop | out_path = path <.> ext |
153 | 4188449c | Iustin Pop | writeFile out_path adata |
154 | 4188449c | Iustin Pop | hPrintf stderr "The cluster state %s has been written to file '%s'\n" |
155 | 4188449c | Iustin Pop | msg out_path |
156 | c32c4e4d | Spyros Trigazis | |
157 | c32c4e4d | Spyros Trigazis | -- | Type describing a data collector basic information. |
158 | c32c4e4d | Spyros Trigazis | data DataCollector = DataCollector |
159 | c32c4e4d | Spyros Trigazis | { dName :: String -- ^ Name of the data collector |
160 | c32c4e4d | Spyros Trigazis | , dCategory :: Maybe DCCategory -- ^ The name of the category |
161 | c32c4e4d | Spyros Trigazis | } |
162 | c32c4e4d | Spyros Trigazis | |
163 | c32c4e4d | Spyros Trigazis | -- | The actual data types for MonD's Data Collectors. |
164 | c32c4e4d | Spyros Trigazis | data Report = CPUavgloadReport CPUavgload |
165 | c32c4e4d | Spyros Trigazis | |
166 | c32c4e4d | Spyros Trigazis | -- | The list of Data Collectors used by hail and hbal. |
167 | c32c4e4d | Spyros Trigazis | collectors :: Options -> [DataCollector] |
168 | c32c4e4d | Spyros Trigazis | collectors opts = |
169 | c32c4e4d | Spyros Trigazis | if optIgnoreDynu opts |
170 | c32c4e4d | Spyros Trigazis | then [] |
171 | c32c4e4d | Spyros Trigazis | else [ DataCollector CPUload.dcName CPUload.dcCategory ] |
172 | c32c4e4d | Spyros Trigazis | |
173 | c62bec27 | Spyros Trigazis | -- | MonDs Data parsed by a mock file. Representing (node name, list of reports |
174 | c62bec27 | Spyros Trigazis | -- produced by MonDs Data Collectors). |
175 | c62bec27 | Spyros Trigazis | type MonDData = (String, [DCReport]) |
176 | c62bec27 | Spyros Trigazis | |
177 | c62bec27 | Spyros Trigazis | -- | A map storing MonDs data. |
178 | c62bec27 | Spyros Trigazis | type MapMonDData = Map.Map String [DCReport] |
179 | c62bec27 | Spyros Trigazis | |
180 | c62bec27 | Spyros Trigazis | -- | Parse MonD data file contents. |
181 | c62bec27 | Spyros Trigazis | pMonDData :: String -> Result [MonDData] |
182 | c62bec27 | Spyros Trigazis | pMonDData input = |
183 | c62bec27 | Spyros Trigazis | loadJSArray "Parsing MonD's answer" input >>= |
184 | c62bec27 | Spyros Trigazis | mapM (pMonDN . J.fromJSObject) |
185 | c62bec27 | Spyros Trigazis | |
186 | c62bec27 | Spyros Trigazis | -- | Parse a node's JSON record. |
187 | c62bec27 | Spyros Trigazis | pMonDN :: JSRecord -> Result MonDData |
188 | c62bec27 | Spyros Trigazis | pMonDN a = do |
189 | c62bec27 | Spyros Trigazis | node <- tryFromObj "Parsing node's name" a "node" |
190 | c62bec27 | Spyros Trigazis | reports <- tryFromObj "Parsing node's reports" a "reports" |
191 | c62bec27 | Spyros Trigazis | return (node, reports) |
192 | c62bec27 | Spyros Trigazis | |
193 | c32c4e4d | Spyros Trigazis | -- | Query all MonDs for all Data Collector. |
194 | c62bec27 | Spyros Trigazis | queryAllMonDDCs :: ClusterData -> Options -> IO ClusterData |
195 | c62bec27 | Spyros Trigazis | queryAllMonDDCs cdata opts = do |
196 | c62bec27 | Spyros Trigazis | map_mDD <- |
197 | c62bec27 | Spyros Trigazis | case optMonDFile opts of |
198 | c62bec27 | Spyros Trigazis | Nothing -> return Nothing |
199 | c62bec27 | Spyros Trigazis | Just fp -> do |
200 | c62bec27 | Spyros Trigazis | monDData_contents <- readFile fp |
201 | c62bec27 | Spyros Trigazis | monDData <- exitIfBad "can't parse MonD data" |
202 | c62bec27 | Spyros Trigazis | . pMonDData $ monDData_contents |
203 | c62bec27 | Spyros Trigazis | return . Just $ Map.fromList monDData |
204 | c32c4e4d | Spyros Trigazis | let (ClusterData _ nl il _ _) = cdata |
205 | c62bec27 | Spyros Trigazis | (nl', il') <- foldM (queryAllMonDs map_mDD) (nl, il) (collectors opts) |
206 | c32c4e4d | Spyros Trigazis | return $ cdata {cdNodes = nl', cdInstances = il'} |
207 | c32c4e4d | Spyros Trigazis | |
208 | c32c4e4d | Spyros Trigazis | -- | Query all MonDs for a single Data Collector. |
209 | c62bec27 | Spyros Trigazis | queryAllMonDs :: Maybe MapMonDData -> (Node.List, Instance.List) |
210 | c62bec27 | Spyros Trigazis | -> DataCollector -> IO (Node.List, Instance.List) |
211 | c62bec27 | Spyros Trigazis | queryAllMonDs m (nl, il) dc = do |
212 | c62bec27 | Spyros Trigazis | elems <- mapM (queryAMonD m dc) (Container.elems nl) |
213 | c32c4e4d | Spyros Trigazis | let elems' = catMaybes elems |
214 | c32c4e4d | Spyros Trigazis | if length elems == length elems' |
215 | c32c4e4d | Spyros Trigazis | then |
216 | c32c4e4d | Spyros Trigazis | let il' = foldl updateUtilData il elems' |
217 | c32c4e4d | Spyros Trigazis | nl' = zip (Container.keys nl) elems' |
218 | c32c4e4d | Spyros Trigazis | in return (Container.fromList nl', il') |
219 | c32c4e4d | Spyros Trigazis | else do |
220 | c32c4e4d | Spyros Trigazis | logWarning $ "Didn't receive an answer by all MonDs, " ++ dName dc |
221 | c32c4e4d | Spyros Trigazis | ++ "'s data will be ignored." |
222 | c32c4e4d | Spyros Trigazis | return (nl,il) |
223 | c32c4e4d | Spyros Trigazis | |
224 | c32c4e4d | Spyros Trigazis | -- | Query a specified MonD for a Data Collector. |
225 | c32c4e4d | Spyros Trigazis | fromCurl :: DataCollector -> Node.Node -> IO (Maybe DCReport) |
226 | c32c4e4d | Spyros Trigazis | fromCurl dc node = do |
227 | c32c4e4d | Spyros Trigazis | (code, !body) <- curlGetString (prepareUrl dc node) [] |
228 | c32c4e4d | Spyros Trigazis | case code of |
229 | c32c4e4d | Spyros Trigazis | CurlOK -> |
230 | c32c4e4d | Spyros Trigazis | case J.decodeStrict body :: J.Result DCReport of |
231 | c32c4e4d | Spyros Trigazis | J.Ok r -> return $ Just r |
232 | c32c4e4d | Spyros Trigazis | J.Error _ -> return Nothing |
233 | c32c4e4d | Spyros Trigazis | _ -> do |
234 | c32c4e4d | Spyros Trigazis | logWarning $ "Failed to contact node's " ++ Node.name node |
235 | c32c4e4d | Spyros Trigazis | ++ " MonD for DC " ++ dName dc |
236 | c32c4e4d | Spyros Trigazis | return Nothing |
237 | c32c4e4d | Spyros Trigazis | |
238 | c32c4e4d | Spyros Trigazis | -- | Return the data from correct combination of a Data Collector |
239 | c32c4e4d | Spyros Trigazis | -- and a DCReport. |
240 | c32c4e4d | Spyros Trigazis | mkReport :: DataCollector -> Maybe DCReport -> Maybe Report |
241 | c32c4e4d | Spyros Trigazis | mkReport dc dcr = |
242 | c32c4e4d | Spyros Trigazis | case dcr of |
243 | c32c4e4d | Spyros Trigazis | Nothing -> Nothing |
244 | c32c4e4d | Spyros Trigazis | Just dcr' -> |
245 | c32c4e4d | Spyros Trigazis | case () of |
246 | c32c4e4d | Spyros Trigazis | _ | CPUload.dcName == dName dc -> |
247 | c32c4e4d | Spyros Trigazis | case fromJVal (dcReportData dcr') :: Result CPUavgload of |
248 | c32c4e4d | Spyros Trigazis | Ok cav -> Just $ CPUavgloadReport cav |
249 | c32c4e4d | Spyros Trigazis | Bad _ -> Nothing |
250 | c32c4e4d | Spyros Trigazis | | otherwise -> Nothing |
251 | c32c4e4d | Spyros Trigazis | |
252 | c62bec27 | Spyros Trigazis | -- | Get data report for the specified Data Collector and Node from the map. |
253 | c62bec27 | Spyros Trigazis | fromFile :: DataCollector -> Node.Node -> MapMonDData -> Maybe DCReport |
254 | c62bec27 | Spyros Trigazis | fromFile dc node m = |
255 | c62bec27 | Spyros Trigazis | let matchDCName dcr = dName dc == dcReportName dcr |
256 | c62bec27 | Spyros Trigazis | in maybe Nothing (L.find matchDCName) $ Map.lookup (Node.name node) m |
257 | c62bec27 | Spyros Trigazis | |
258 | c32c4e4d | Spyros Trigazis | -- | Query a MonD for a single Data Collector. |
259 | c62bec27 | Spyros Trigazis | queryAMonD :: Maybe MapMonDData -> DataCollector -> Node.Node |
260 | c62bec27 | Spyros Trigazis | -> IO (Maybe Node.Node) |
261 | c62bec27 | Spyros Trigazis | queryAMonD m dc node = do |
262 | c62bec27 | Spyros Trigazis | dcReport <- |
263 | c62bec27 | Spyros Trigazis | case m of |
264 | c62bec27 | Spyros Trigazis | Nothing -> fromCurl dc node |
265 | c62bec27 | Spyros Trigazis | Just m' -> return $ fromFile dc node m' |
266 | c32c4e4d | Spyros Trigazis | case mkReport dc dcReport of |
267 | c32c4e4d | Spyros Trigazis | Nothing -> return Nothing |
268 | c32c4e4d | Spyros Trigazis | Just report -> |
269 | c32c4e4d | Spyros Trigazis | case report of |
270 | c32c4e4d | Spyros Trigazis | CPUavgloadReport cav -> |
271 | c32c4e4d | Spyros Trigazis | let ct = cavCpuTotal cav |
272 | c32c4e4d | Spyros Trigazis | du = Node.utilLoad node |
273 | c32c4e4d | Spyros Trigazis | du' = du {cpuWeight = ct} |
274 | c32c4e4d | Spyros Trigazis | in return $ Just node {Node.utilLoad = du'} |
275 | c32c4e4d | Spyros Trigazis | |
276 | c32c4e4d | Spyros Trigazis | -- | Update utilization data. |
277 | c32c4e4d | Spyros Trigazis | updateUtilData :: Instance.List -> Node.Node -> Instance.List |
278 | c32c4e4d | Spyros Trigazis | updateUtilData il node = |
279 | c32c4e4d | Spyros Trigazis | let ct = cpuWeight (Node.utilLoad node) |
280 | c32c4e4d | Spyros Trigazis | n_uCpu = Node.uCpu node |
281 | c32c4e4d | Spyros Trigazis | upd inst = |
282 | c32c4e4d | Spyros Trigazis | if Node.idx node == Instance.pNode inst |
283 | c32c4e4d | Spyros Trigazis | then |
284 | c32c4e4d | Spyros Trigazis | let i_vcpus = Instance.vcpus inst |
285 | c32c4e4d | Spyros Trigazis | i_util = ct / fromIntegral n_uCpu * fromIntegral i_vcpus |
286 | c32c4e4d | Spyros Trigazis | i_du = Instance.util inst |
287 | c32c4e4d | Spyros Trigazis | i_du' = i_du {cpuWeight = i_util} |
288 | c32c4e4d | Spyros Trigazis | in inst {Instance.util = i_du'} |
289 | c32c4e4d | Spyros Trigazis | else inst |
290 | c32c4e4d | Spyros Trigazis | in Container.map upd il |
291 | c32c4e4d | Spyros Trigazis | |
292 | c32c4e4d | Spyros Trigazis | -- | Prepare url to query a single collector. |
293 | c32c4e4d | Spyros Trigazis | prepareUrl :: DataCollector -> Node.Node -> URLString |
294 | c32c4e4d | Spyros Trigazis | prepareUrl dc node = |
295 | c32c4e4d | Spyros Trigazis | Node.name node ++ ":" ++ show C.defaultMondPort ++ "/" |
296 | c32c4e4d | Spyros Trigazis | ++ show C.mondLatestApiVersion ++ "/report/" ++ |
297 | c32c4e4d | Spyros Trigazis | getDCCName (dCategory dc) ++ "/" ++ dName dc |
298 | c32c4e4d | Spyros Trigazis | |
299 | c32c4e4d | Spyros Trigazis | -- | Get Category Name. |
300 | c32c4e4d | Spyros Trigazis | getDCCName :: Maybe DCCategory -> String |
301 | c32c4e4d | Spyros Trigazis | getDCCName dcc = |
302 | c32c4e4d | Spyros Trigazis | case dcc of |
303 | c32c4e4d | Spyros Trigazis | Nothing -> "default" |
304 | c32c4e4d | Spyros Trigazis | Just c -> getCategoryName c |