Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Monitoring / Server.hs @ e817723c

History | View | Annotate | Download (8.5 kB)

1 13cc7b84 Michele Tartara
{-# LANGUAGE OverloadedStrings #-}
2 13cc7b84 Michele Tartara
3 13cc7b84 Michele Tartara
{-| Implementation of the Ganeti confd server functionality.
4 13cc7b84 Michele Tartara
5 13cc7b84 Michele Tartara
-}
6 13cc7b84 Michele Tartara
7 13cc7b84 Michele Tartara
{-
8 13cc7b84 Michele Tartara
9 13cc7b84 Michele Tartara
Copyright (C) 2013 Google Inc.
10 13cc7b84 Michele Tartara
11 13cc7b84 Michele Tartara
This program is free software; you can redistribute it and/or modify
12 13cc7b84 Michele Tartara
it under the terms of the GNU General Public License as published by
13 13cc7b84 Michele Tartara
the Free Software Foundation; either version 2 of the License, or
14 13cc7b84 Michele Tartara
(at your option) any later version.
15 13cc7b84 Michele Tartara
16 13cc7b84 Michele Tartara
This program is distributed in the hope that it will be useful, but
17 13cc7b84 Michele Tartara
WITHOUT ANY WARRANTY; without even the implied warranty of
18 13cc7b84 Michele Tartara
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 13cc7b84 Michele Tartara
General Public License for more details.
20 13cc7b84 Michele Tartara
21 13cc7b84 Michele Tartara
You should have received a copy of the GNU General Public License
22 13cc7b84 Michele Tartara
along with this program; if not, write to the Free Software
23 13cc7b84 Michele Tartara
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 13cc7b84 Michele Tartara
02110-1301, USA.
25 13cc7b84 Michele Tartara
26 13cc7b84 Michele Tartara
-}
27 13cc7b84 Michele Tartara
28 13cc7b84 Michele Tartara
module Ganeti.Monitoring.Server
29 13cc7b84 Michele Tartara
  ( main
30 13cc7b84 Michele Tartara
  , checkMain
31 13cc7b84 Michele Tartara
  , prepMain
32 13cc7b84 Michele Tartara
  ) where
33 13cc7b84 Michele Tartara
34 423b2dd5 Michele Tartara
import Control.Applicative
35 423b2dd5 Michele Tartara
import Control.Monad
36 db1ad1d5 Michele Tartara
import Control.Monad.IO.Class
37 db1ad1d5 Michele Tartara
import Data.ByteString.Char8 hiding (map, filter, find)
38 db1ad1d5 Michele Tartara
import Data.List
39 3792fa8e Spyros Trigazis
import qualified Data.Map as Map
40 eb65c915 Michele Tartara
import Snap.Core
41 eb65c915 Michele Tartara
import Snap.Http.Server
42 eb65c915 Michele Tartara
import qualified Text.JSON as J
43 3792fa8e Spyros Trigazis
import Control.Concurrent
44 eb65c915 Michele Tartara
45 db1ad1d5 Michele Tartara
import qualified Ganeti.BasicTypes as BT
46 13cc7b84 Michele Tartara
import Ganeti.Daemon
47 3792fa8e Spyros Trigazis
import qualified Ganeti.DataCollectors.CPUload as CPUload
48 aab0927c Michele Tartara
import qualified Ganeti.DataCollectors.Diskstats as Diskstats
49 ecb783f0 Michele Tartara
import qualified Ganeti.DataCollectors.Drbd as Drbd
50 8a049311 Michele Tartara
import qualified Ganeti.DataCollectors.InstStatus as InstStatus
51 006d6bc9 Michele Tartara
import qualified Ganeti.DataCollectors.Lv as Lv
52 ecb783f0 Michele Tartara
import Ganeti.DataCollectors.Types
53 eb65c915 Michele Tartara
import qualified Ganeti.Constants as C
54 34be621a Jose A. Lopes
import Ganeti.Runtime
55 13cc7b84 Michele Tartara
56 13cc7b84 Michele Tartara
-- * Types and constants definitions
57 13cc7b84 Michele Tartara
58 13cc7b84 Michele Tartara
-- | Type alias for checkMain results.
59 13cc7b84 Michele Tartara
type CheckResult = ()
60 13cc7b84 Michele Tartara
61 13cc7b84 Michele Tartara
-- | Type alias for prepMain results.
62 eb65c915 Michele Tartara
type PrepResult = Config Snap ()
63 eb65c915 Michele Tartara
64 eb65c915 Michele Tartara
-- | Version of the latest supported http API.
65 eb65c915 Michele Tartara
latestAPIVersion :: Int
66 690e509d Spyros Trigazis
latestAPIVersion = C.mondLatestApiVersion
67 eb65c915 Michele Tartara
68 3792fa8e Spyros Trigazis
-- | A report of a data collector might be stateful or stateless.
69 3792fa8e Spyros Trigazis
data Report = StatelessR (IO DCReport)
70 3792fa8e Spyros Trigazis
            | StatefulR (Maybe CollectorData -> IO DCReport)
71 3792fa8e Spyros Trigazis
72 ecb783f0 Michele Tartara
-- | Type describing a data collector basic information
73 ecb783f0 Michele Tartara
data DataCollector = DataCollector
74 ecb783f0 Michele Tartara
  { dName     :: String           -- ^ Name of the data collector
75 ecb783f0 Michele Tartara
  , dCategory :: Maybe DCCategory -- ^ Category (storage, instance, ecc)
76 ecb783f0 Michele Tartara
                                  --   of the collector
77 ecb783f0 Michele Tartara
  , dKind     :: DCKind           -- ^ Kind (performance or status reporting) of
78 ecb783f0 Michele Tartara
                                  --   the data collector
79 3792fa8e Spyros Trigazis
  , dReport   :: Report           -- ^ Report produced by the collector
80 3792fa8e Spyros Trigazis
  , dUpdate   :: Maybe (Maybe CollectorData -> IO CollectorData)
81 3792fa8e Spyros Trigazis
                                  -- ^ Update operation for stateful collectors.
82 ecb783f0 Michele Tartara
  }
83 ecb783f0 Michele Tartara
84 3792fa8e Spyros Trigazis
85 ecb783f0 Michele Tartara
-- | The list of available builtin data collectors.
86 ecb783f0 Michele Tartara
collectors :: [DataCollector]
87 ecb783f0 Michele Tartara
collectors =
88 aab0927c Michele Tartara
  [ DataCollector Diskstats.dcName Diskstats.dcCategory Diskstats.dcKind
89 3792fa8e Spyros Trigazis
      (StatelessR Diskstats.dcReport) Nothing
90 3792fa8e Spyros Trigazis
  , DataCollector Drbd.dcName Drbd.dcCategory Drbd.dcKind
91 3792fa8e Spyros Trigazis
      (StatelessR Drbd.dcReport) Nothing
92 8a049311 Michele Tartara
  , DataCollector InstStatus.dcName InstStatus.dcCategory InstStatus.dcKind
93 3792fa8e Spyros Trigazis
      (StatelessR InstStatus.dcReport) Nothing
94 3792fa8e Spyros Trigazis
  , DataCollector Lv.dcName Lv.dcCategory Lv.dcKind
95 3792fa8e Spyros Trigazis
      (StatelessR Lv.dcReport) Nothing
96 3792fa8e Spyros Trigazis
  , DataCollector CPUload.dcName CPUload.dcCategory CPUload.dcKind
97 3792fa8e Spyros Trigazis
      (StatefulR CPUload.dcReport) (Just CPUload.dcUpdate)
98 ecb783f0 Michele Tartara
  ]
99 ecb783f0 Michele Tartara
100 eb65c915 Michele Tartara
-- * Configuration handling
101 eb65c915 Michele Tartara
102 eb65c915 Michele Tartara
-- | The default configuration for the HTTP server.
103 34be621a Jose A. Lopes
defaultHttpConf :: FilePath -> FilePath -> Config Snap ()
104 34be621a Jose A. Lopes
defaultHttpConf accessLog errorLog =
105 34be621a Jose A. Lopes
  setAccessLog (ConfigFileLog accessLog) .
106 eb65c915 Michele Tartara
  setCompression False .
107 34be621a Jose A. Lopes
  setErrorLog (ConfigFileLog errorLog) $
108 eb65c915 Michele Tartara
  setVerbose False
109 eb65c915 Michele Tartara
  emptyConfig
110 13cc7b84 Michele Tartara
111 13cc7b84 Michele Tartara
-- * Helper functions
112 13cc7b84 Michele Tartara
113 13cc7b84 Michele Tartara
-- | Check function for the monitoring agent.
114 13cc7b84 Michele Tartara
checkMain :: CheckFn CheckResult
115 13cc7b84 Michele Tartara
checkMain _ = return $ Right ()
116 13cc7b84 Michele Tartara
117 13cc7b84 Michele Tartara
-- | Prepare function for monitoring agent.
118 13cc7b84 Michele Tartara
prepMain :: PrepFn CheckResult PrepResult
119 34be621a Jose A. Lopes
prepMain opts _ = do
120 1c31b263 Jose A. Lopes
  accessLog <- daemonsExtraLogFile GanetiMond AccessLog
121 1c31b263 Jose A. Lopes
  errorLog <- daemonsExtraLogFile GanetiMond ErrorLog
122 1c31b263 Jose A. Lopes
  return $
123 1c31b263 Jose A. Lopes
    setPort
124 1c31b263 Jose A. Lopes
      (maybe C.defaultMondPort fromIntegral (optPort opts))
125 1c31b263 Jose A. Lopes
      (defaultHttpConf accessLog errorLog)
126 eb65c915 Michele Tartara
127 eb65c915 Michele Tartara
-- * Query answers
128 eb65c915 Michele Tartara
129 eb65c915 Michele Tartara
-- | Reply to the supported API version numbers query.
130 eb65c915 Michele Tartara
versionQ :: Snap ()
131 423b2dd5 Michele Tartara
versionQ = writeBS . pack $ J.encode [latestAPIVersion]
132 423b2dd5 Michele Tartara
133 423b2dd5 Michele Tartara
-- | Version 1 of the monitoring HTTP API.
134 3792fa8e Spyros Trigazis
version1Api :: MVar CollectorMap -> Snap ()
135 3792fa8e Spyros Trigazis
version1Api mvar =
136 423b2dd5 Michele Tartara
  let returnNull = writeBS . pack $ J.encode J.JSNull :: Snap ()
137 423b2dd5 Michele Tartara
  in ifTop returnNull <|>
138 423b2dd5 Michele Tartara
     route
139 423b2dd5 Michele Tartara
       [ ("list", listHandler)
140 3792fa8e Spyros Trigazis
       , ("report", reportHandler mvar)
141 423b2dd5 Michele Tartara
       ]
142 423b2dd5 Michele Tartara
143 ecb783f0 Michele Tartara
-- | Get the JSON representation of a data collector to be used in the collector
144 ecb783f0 Michele Tartara
-- list.
145 ecb783f0 Michele Tartara
dcListItem :: DataCollector -> J.JSValue
146 ecb783f0 Michele Tartara
dcListItem dc =
147 ecb783f0 Michele Tartara
  J.JSArray
148 ecb783f0 Michele Tartara
    [ J.showJSON $ dName dc
149 ecb783f0 Michele Tartara
    , maybe J.JSNull J.showJSON $ dCategory dc
150 ecb783f0 Michele Tartara
    , J.showJSON $ dKind dc
151 ecb783f0 Michele Tartara
    ]
152 ecb783f0 Michele Tartara
153 423b2dd5 Michele Tartara
-- | Handler for returning lists.
154 423b2dd5 Michele Tartara
listHandler :: Snap ()
155 423b2dd5 Michele Tartara
listHandler =
156 ecb783f0 Michele Tartara
  dir "collectors" . writeBS . pack . J.encode $ map dcListItem collectors
157 423b2dd5 Michele Tartara
158 423b2dd5 Michele Tartara
-- | Handler for returning data collector reports.
159 3792fa8e Spyros Trigazis
reportHandler :: MVar CollectorMap -> Snap ()
160 3792fa8e Spyros Trigazis
reportHandler mvar =
161 423b2dd5 Michele Tartara
  route
162 3792fa8e Spyros Trigazis
    [ ("all", allReports mvar)
163 3792fa8e Spyros Trigazis
    , (":category/:collector", oneReport mvar)
164 e580e9f7 Michele Tartara
    ] <|>
165 e580e9f7 Michele Tartara
  errorReport
166 423b2dd5 Michele Tartara
167 db1ad1d5 Michele Tartara
-- | Return the report of all the available collectors.
168 3792fa8e Spyros Trigazis
allReports :: MVar CollectorMap -> Snap ()
169 3792fa8e Spyros Trigazis
allReports mvar = do
170 3792fa8e Spyros Trigazis
  reports <- mapM (liftIO . getReport mvar) collectors
171 6327828e Michele Tartara
  writeBS . pack . J.encode $ reports
172 423b2dd5 Michele Tartara
173 3792fa8e Spyros Trigazis
-- | Takes the CollectorMap and a DataCollector and returns the report for this
174 3792fa8e Spyros Trigazis
-- collector.
175 3792fa8e Spyros Trigazis
getReport :: MVar CollectorMap -> DataCollector -> IO DCReport
176 3792fa8e Spyros Trigazis
getReport mvar collector =
177 3792fa8e Spyros Trigazis
  case dReport collector of
178 3792fa8e Spyros Trigazis
    StatelessR r -> r
179 3792fa8e Spyros Trigazis
    StatefulR r -> do
180 3792fa8e Spyros Trigazis
      colData <- getColData (dName collector) mvar
181 3792fa8e Spyros Trigazis
      r colData
182 3792fa8e Spyros Trigazis
183 3792fa8e Spyros Trigazis
-- | Returns the data for the corresponding collector.
184 3792fa8e Spyros Trigazis
getColData :: String -> MVar CollectorMap -> IO (Maybe CollectorData)
185 3792fa8e Spyros Trigazis
getColData name mvar = do
186 3792fa8e Spyros Trigazis
  m <- readMVar mvar
187 3792fa8e Spyros Trigazis
  return $ Map.lookup name m
188 3792fa8e Spyros Trigazis
189 db1ad1d5 Michele Tartara
-- | Returns a category given its name.
190 db1ad1d5 Michele Tartara
-- If "collector" is given as the name, the collector has no category, and
191 db1ad1d5 Michele Tartara
-- Nothing will be returned.
192 db1ad1d5 Michele Tartara
catFromName :: String -> BT.Result (Maybe DCCategory)
193 db1ad1d5 Michele Tartara
catFromName "instance"   = BT.Ok $ Just DCInstance
194 db1ad1d5 Michele Tartara
catFromName "storage"    = BT.Ok $ Just DCStorage
195 db1ad1d5 Michele Tartara
catFromName "daemon"     = BT.Ok $ Just DCDaemon
196 db1ad1d5 Michele Tartara
catFromName "hypervisor" = BT.Ok $ Just DCHypervisor
197 db1ad1d5 Michele Tartara
catFromName "default"    = BT.Ok Nothing
198 db1ad1d5 Michele Tartara
catFromName _            = BT.Bad "No such category"
199 db1ad1d5 Michele Tartara
200 e580e9f7 Michele Tartara
errorReport :: Snap ()
201 e580e9f7 Michele Tartara
errorReport = do
202 e580e9f7 Michele Tartara
  modifyResponse $ setResponseStatus 404 "Not found"
203 e580e9f7 Michele Tartara
  writeBS "Unable to produce a report for the requested resource"
204 e580e9f7 Michele Tartara
205 e580e9f7 Michele Tartara
error404 :: Snap ()
206 e580e9f7 Michele Tartara
error404 = do
207 e580e9f7 Michele Tartara
  modifyResponse $ setResponseStatus 404 "Not found"
208 e580e9f7 Michele Tartara
  writeBS "Resource not found"
209 e580e9f7 Michele Tartara
210 3792fa8e Spyros Trigazis
-- | Return the report of one collector.
211 3792fa8e Spyros Trigazis
oneReport :: MVar CollectorMap -> Snap ()
212 3792fa8e Spyros Trigazis
oneReport mvar = do
213 db1ad1d5 Michele Tartara
  categoryName <- fmap (maybe mzero unpack) $ getParam "category"
214 db1ad1d5 Michele Tartara
  collectorName <- fmap (maybe mzero unpack) $ getParam "collector"
215 db1ad1d5 Michele Tartara
  category <-
216 db1ad1d5 Michele Tartara
    case catFromName categoryName of
217 db1ad1d5 Michele Tartara
      BT.Ok cat -> return cat
218 db1ad1d5 Michele Tartara
      BT.Bad msg -> fail msg
219 db1ad1d5 Michele Tartara
  collector <-
220 db1ad1d5 Michele Tartara
    case
221 db1ad1d5 Michele Tartara
      find (\col -> collectorName == dName col) $
222 db1ad1d5 Michele Tartara
        filter (\c -> category == dCategory c) collectors of
223 db1ad1d5 Michele Tartara
      Just col -> return col
224 db1ad1d5 Michele Tartara
      Nothing -> fail "Unable to find the requested collector"
225 3792fa8e Spyros Trigazis
  dcr <- liftIO $ getReport mvar collector
226 3792fa8e Spyros Trigazis
  writeBS . pack . J.encode $ dcr
227 eb65c915 Michele Tartara
228 eb65c915 Michele Tartara
-- | The function implementing the HTTP API of the monitoring agent.
229 3792fa8e Spyros Trigazis
monitoringApi :: MVar CollectorMap -> Snap ()
230 3792fa8e Spyros Trigazis
monitoringApi mvar =
231 423b2dd5 Michele Tartara
  ifTop versionQ <|>
232 3792fa8e Spyros Trigazis
  dir "1" (version1Api mvar) <|>
233 e580e9f7 Michele Tartara
  error404
234 13cc7b84 Michele Tartara
235 3792fa8e Spyros Trigazis
-- | The function collecting data for each data collector providing a dcUpdate
236 3792fa8e Spyros Trigazis
-- function.
237 3792fa8e Spyros Trigazis
collect :: CollectorMap -> DataCollector -> IO CollectorMap
238 3792fa8e Spyros Trigazis
collect m collector =
239 3792fa8e Spyros Trigazis
  case dUpdate collector of
240 3792fa8e Spyros Trigazis
    Nothing -> return m
241 3792fa8e Spyros Trigazis
    Just update -> do
242 3792fa8e Spyros Trigazis
      let name = dName collector
243 3792fa8e Spyros Trigazis
          existing = Map.lookup name m
244 3792fa8e Spyros Trigazis
      new_data <- update existing
245 3792fa8e Spyros Trigazis
      return $ Map.insert name new_data m
246 3792fa8e Spyros Trigazis
247 3792fa8e Spyros Trigazis
-- | Invokes collect for each data collector.
248 3792fa8e Spyros Trigazis
collection :: CollectorMap -> IO CollectorMap
249 3792fa8e Spyros Trigazis
collection m = foldM collect m collectors
250 3792fa8e Spyros Trigazis
251 3792fa8e Spyros Trigazis
-- | The thread responsible for the periodical collection of data for each data
252 3792fa8e Spyros Trigazis
-- data collector.
253 3792fa8e Spyros Trigazis
collectord :: MVar CollectorMap -> IO ()
254 3792fa8e Spyros Trigazis
collectord mvar = do
255 3792fa8e Spyros Trigazis
  m <- takeMVar mvar
256 3792fa8e Spyros Trigazis
  m' <- collection m
257 3792fa8e Spyros Trigazis
  putMVar mvar m'
258 3792fa8e Spyros Trigazis
  threadDelay $ 10^(6 :: Int) * C.mondTimeInterval
259 3792fa8e Spyros Trigazis
  collectord mvar
260 3792fa8e Spyros Trigazis
261 13cc7b84 Michele Tartara
-- | Main function.
262 13cc7b84 Michele Tartara
main :: MainFn CheckResult PrepResult
263 3792fa8e Spyros Trigazis
main _ _ httpConf = do
264 3792fa8e Spyros Trigazis
  mvar <- newMVar Map.empty
265 3792fa8e Spyros Trigazis
  _ <- forkIO $ collectord mvar
266 3792fa8e Spyros Trigazis
  httpServe httpConf . method GET $ monitoringApi mvar