46 |
46 |
import Text.Printf (hPrintf)
|
47 |
47 |
|
48 |
48 |
import qualified Text.JSON as J
|
|
49 |
import qualified Data.Map as Map
|
|
50 |
import qualified Data.List as L
|
49 |
51 |
|
50 |
52 |
import qualified Ganeti.Constants as C
|
51 |
53 |
import qualified Ganeti.DataCollectors.CPUload as CPUload
|
... | ... | |
167 |
169 |
then []
|
168 |
170 |
else [ DataCollector CPUload.dcName CPUload.dcCategory ]
|
169 |
171 |
|
|
172 |
-- | MonDs Data parsed by a mock file. Representing (node name, list of reports
|
|
173 |
-- produced by MonDs Data Collectors).
|
|
174 |
type MonDData = (String, [DCReport])
|
|
175 |
|
|
176 |
-- | A map storing MonDs data.
|
|
177 |
type MapMonDData = Map.Map String [DCReport]
|
|
178 |
|
|
179 |
-- | Parse MonD data file contents.
|
|
180 |
pMonDData :: String -> Result [MonDData]
|
|
181 |
pMonDData input =
|
|
182 |
loadJSArray "Parsing MonD's answer" input >>=
|
|
183 |
mapM (pMonDN . J.fromJSObject)
|
|
184 |
|
|
185 |
-- | Parse a node's JSON record.
|
|
186 |
pMonDN :: JSRecord -> Result MonDData
|
|
187 |
pMonDN a = do
|
|
188 |
node <- tryFromObj "Parsing node's name" a "node"
|
|
189 |
reports <- tryFromObj "Parsing node's reports" a "reports"
|
|
190 |
return (node, reports)
|
|
191 |
|
170 |
192 |
-- | Query all MonDs for all Data Collector.
|
171 |
|
queryAllMonDDCs :: ClusterData -> IO ClusterData
|
172 |
|
queryAllMonDDCs cdata = do
|
|
193 |
queryAllMonDDCs :: ClusterData -> Options -> IO ClusterData
|
|
194 |
queryAllMonDDCs cdata opts = do
|
|
195 |
map_mDD <-
|
|
196 |
case optMonDFile opts of
|
|
197 |
Nothing -> return Nothing
|
|
198 |
Just fp -> do
|
|
199 |
monDData_contents <- readFile fp
|
|
200 |
monDData <- exitIfBad "can't parse MonD data"
|
|
201 |
. pMonDData $ monDData_contents
|
|
202 |
return . Just $ Map.fromList monDData
|
173 |
203 |
let (ClusterData _ nl il _ _) = cdata
|
174 |
|
(nl', il') <- foldM queryAllMonDs (nl, il) (collectors opts)
|
|
204 |
(nl', il') <- foldM (queryAllMonDs map_mDD) (nl, il) (collectors opts)
|
175 |
205 |
return $ cdata {cdNodes = nl', cdInstances = il'}
|
176 |
206 |
|
177 |
207 |
-- | Query all MonDs for a single Data Collector.
|
178 |
|
queryAllMonDs :: (Node.List, Instance.List) -> DataCollector
|
179 |
|
-> IO (Node.List, Instance.List)
|
180 |
|
queryAllMonDs (nl, il) dc = do
|
181 |
|
elems <- mapM (queryAMonD dc) (Container.elems nl)
|
|
208 |
queryAllMonDs :: Maybe MapMonDData -> (Node.List, Instance.List)
|
|
209 |
-> DataCollector -> IO (Node.List, Instance.List)
|
|
210 |
queryAllMonDs m (nl, il) dc = do
|
|
211 |
elems <- mapM (queryAMonD m dc) (Container.elems nl)
|
182 |
212 |
let elems' = catMaybes elems
|
183 |
213 |
if length elems == length elems'
|
184 |
214 |
then
|
... | ... | |
218 |
248 |
Bad _ -> Nothing
|
219 |
249 |
| otherwise -> Nothing
|
220 |
250 |
|
|
251 |
-- | Get data report for the specified Data Collector and Node from the map.
|
|
252 |
fromFile :: DataCollector -> Node.Node -> MapMonDData -> Maybe DCReport
|
|
253 |
fromFile dc node m =
|
|
254 |
let matchDCName dcr = dName dc == dcReportName dcr
|
|
255 |
in maybe Nothing (L.find matchDCName) $ Map.lookup (Node.name node) m
|
|
256 |
|
221 |
257 |
-- | Query a MonD for a single Data Collector.
|
222 |
|
queryAMonD :: DataCollector -> Node.Node -> IO (Maybe Node.Node)
|
223 |
|
queryAMonD dc node = do
|
224 |
|
dcReport <- fromCurl dc node
|
|
258 |
queryAMonD :: Maybe MapMonDData -> DataCollector -> Node.Node
|
|
259 |
-> IO (Maybe Node.Node)
|
|
260 |
queryAMonD m dc node = do
|
|
261 |
dcReport <-
|
|
262 |
case m of
|
|
263 |
Nothing -> fromCurl dc node
|
|
264 |
Just m' -> return $ fromFile dc node m'
|
225 |
265 |
case mkReport dc dcReport of
|
226 |
266 |
Nothing -> return Nothing
|
227 |
267 |
Just report ->
|