Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / DataCollectors / Drbd.hs @ 4fe04580

History | View | Annotate | Download (7.8 kB)

1 332b1340 Michele Tartara
{-| DRBD data collector.
2 332b1340 Michele Tartara
3 332b1340 Michele Tartara
-}
4 332b1340 Michele Tartara
5 332b1340 Michele Tartara
{-
6 332b1340 Michele Tartara
7 ddceb4c5 Michele Tartara
Copyright (C) 2012, 2013 Google Inc.
8 332b1340 Michele Tartara
9 332b1340 Michele Tartara
This program is free software; you can redistribute it and/or modify
10 332b1340 Michele Tartara
it under the terms of the GNU General Public License as published by
11 332b1340 Michele Tartara
the Free Software Foundation; either version 2 of the License, or
12 332b1340 Michele Tartara
(at your option) any later version.
13 332b1340 Michele Tartara
14 332b1340 Michele Tartara
This program is distributed in the hope that it will be useful, but
15 332b1340 Michele Tartara
WITHOUT ANY WARRANTY; without even the implied warranty of
16 332b1340 Michele Tartara
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 332b1340 Michele Tartara
General Public License for more details.
18 332b1340 Michele Tartara
19 332b1340 Michele Tartara
You should have received a copy of the GNU General Public License
20 332b1340 Michele Tartara
along with this program; if not, write to the Free Software
21 332b1340 Michele Tartara
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 332b1340 Michele Tartara
02110-1301, USA.
23 332b1340 Michele Tartara
24 332b1340 Michele Tartara
-}
25 332b1340 Michele Tartara
26 332b1340 Michele Tartara
module Ganeti.DataCollectors.Drbd
27 332b1340 Michele Tartara
  ( main
28 332b1340 Michele Tartara
  , options
29 332b1340 Michele Tartara
  , arguments
30 ddceb4c5 Michele Tartara
  , dcName
31 a895fa19 Michele Tartara
  , dcVersion
32 834dc290 Michele Tartara
  , dcFormatVersion
33 f0e4b2a4 Michele Tartara
  , dcCategory
34 54c7dff7 Michele Tartara
  , dcKind
35 75706f3a Michele Tartara
  , dcReport
36 332b1340 Michele Tartara
  ) where
37 332b1340 Michele Tartara
38 332b1340 Michele Tartara
39 332b1340 Michele Tartara
import qualified Control.Exception as E
40 d78970ba Michele Tartara
import Control.Monad
41 332b1340 Michele Tartara
import Data.Attoparsec.Text.Lazy as A
42 2d1c753d Michele Tartara
import Data.List
43 d78970ba Michele Tartara
import Data.Maybe
44 332b1340 Michele Tartara
import Data.Text.Lazy (pack, unpack)
45 d78970ba Michele Tartara
import Network.BSD (getHostName)
46 d78970ba Michele Tartara
import qualified Text.JSON as J
47 332b1340 Michele Tartara
48 332b1340 Michele Tartara
import qualified Ganeti.BasicTypes as BT
49 332b1340 Michele Tartara
import qualified Ganeti.Constants as C
50 332b1340 Michele Tartara
import Ganeti.Block.Drbd.Parser(drbdStatusParser)
51 2d1c753d Michele Tartara
import Ganeti.Block.Drbd.Types
52 332b1340 Michele Tartara
import Ganeti.Common
53 d78970ba Michele Tartara
import Ganeti.Confd.Client
54 d78970ba Michele Tartara
import Ganeti.Confd.Types
55 55abd2c7 Iustin Pop
import Ganeti.DataCollectors.CLI
56 e71c47d3 Michele Tartara
import Ganeti.DataCollectors.Types
57 332b1340 Michele Tartara
import Ganeti.Utils
58 332b1340 Michele Tartara
59 332b1340 Michele Tartara
60 332b1340 Michele Tartara
-- | The default path of the DRBD status file.
61 332b1340 Michele Tartara
-- It is hardcoded because it is not likely to change.
62 332b1340 Michele Tartara
defaultFile :: FilePath
63 332b1340 Michele Tartara
defaultFile = C.drbdStatusFile
64 332b1340 Michele Tartara
65 332b1340 Michele Tartara
-- | The default setting for the maximum amount of not parsed character to
66 332b1340 Michele Tartara
-- print in case of error.
67 332b1340 Michele Tartara
-- It is set to use most of the screen estate on a standard 80x25 terminal.
68 332b1340 Michele Tartara
-- TODO: add the possibility to set this with a command line parameter.
69 332b1340 Michele Tartara
defaultCharNum :: Int
70 332b1340 Michele Tartara
defaultCharNum = 80*20
71 332b1340 Michele Tartara
72 e71c47d3 Michele Tartara
-- | The name of this data collector.
73 e71c47d3 Michele Tartara
dcName :: String
74 e71c47d3 Michele Tartara
dcName = "drbd"
75 e71c47d3 Michele Tartara
76 a895fa19 Michele Tartara
-- | The version of this data collector.
77 a895fa19 Michele Tartara
dcVersion :: DCVersion
78 a895fa19 Michele Tartara
dcVersion = DCVerBuiltin
79 a895fa19 Michele Tartara
80 e71c47d3 Michele Tartara
-- | The version number for the data format of this data collector.
81 e71c47d3 Michele Tartara
dcFormatVersion :: Int
82 e71c47d3 Michele Tartara
dcFormatVersion = 1
83 e71c47d3 Michele Tartara
84 f0e4b2a4 Michele Tartara
-- | The category of this data collector.
85 f0e4b2a4 Michele Tartara
dcCategory :: Maybe DCCategory
86 f0e4b2a4 Michele Tartara
dcCategory = Just DCStorage
87 f0e4b2a4 Michele Tartara
88 54c7dff7 Michele Tartara
-- | The kind of this data collector.
89 54c7dff7 Michele Tartara
dcKind :: DCKind
90 54c7dff7 Michele Tartara
dcKind = DCKStatus
91 54c7dff7 Michele Tartara
92 8c5419ee Michele Tartara
-- | The data exported by the data collector, taken from the default location.
93 75706f3a Michele Tartara
dcReport :: IO DCReport
94 75706f3a Michele Tartara
dcReport = buildDCReport defaultFile Nothing
95 8c5419ee Michele Tartara
96 7a171e3f Michele Tartara
-- * Command line options
97 7a171e3f Michele Tartara
98 332b1340 Michele Tartara
options :: IO [OptType]
99 d78970ba Michele Tartara
options =
100 d78970ba Michele Tartara
  return
101 d78970ba Michele Tartara
    [ oDrbdStatus
102 d78970ba Michele Tartara
    , oDrbdPairing
103 d78970ba Michele Tartara
    ]
104 332b1340 Michele Tartara
105 332b1340 Michele Tartara
-- | The list of arguments supported by the program.
106 332b1340 Michele Tartara
arguments :: [ArgCompletion]
107 d78970ba Michele Tartara
arguments = [ArgCompletion OptComplFile 0 (Just 0)]
108 332b1340 Michele Tartara
109 d78970ba Michele Tartara
-- | Get information about the pairing of DRBD minors and Ganeti instances
110 d78970ba Michele Tartara
-- on the current node. The information is taken from the Confd client
111 d78970ba Michele Tartara
-- or, if a filename is specified, from a JSON encoded file (for testing
112 d78970ba Michele Tartara
-- purposes).
113 d78970ba Michele Tartara
getPairingInfo :: Maybe String -> IO (BT.Result [DrbdInstMinor])
114 d78970ba Michele Tartara
getPairingInfo Nothing = do
115 d78970ba Michele Tartara
  curNode <- getHostName
116 7dc27988 Michele Tartara
  client <- getConfdClient Nothing Nothing
117 d78970ba Michele Tartara
  reply <- query client ReqNodeDrbd $ PlainQuery curNode
118 d78970ba Michele Tartara
  return $
119 d78970ba Michele Tartara
    case fmap (J.readJSONs . confdReplyAnswer) reply of
120 d78970ba Michele Tartara
      Just (J.Ok instMinor) -> BT.Ok instMinor
121 d78970ba Michele Tartara
      Just (J.Error msg) -> BT.Bad msg
122 d78970ba Michele Tartara
      Nothing -> BT.Bad "No answer from the Confd server"
123 d78970ba Michele Tartara
getPairingInfo (Just filename) = do
124 d78970ba Michele Tartara
  content <- readFile filename
125 d78970ba Michele Tartara
  return $
126 d78970ba Michele Tartara
    case J.decode content of
127 d78970ba Michele Tartara
      J.Ok instMinor -> BT.Ok instMinor
128 d78970ba Michele Tartara
      J.Error msg -> BT.Bad msg
129 d78970ba Michele Tartara
130 2d1c753d Michele Tartara
-- | Compute the status code and message, given the current DRBD data
131 2d1c753d Michele Tartara
-- The final state will have the code corresponding to the worst code of
132 2d1c753d Michele Tartara
-- all the devices, and the error message given from the concatenation of the
133 2d1c753d Michele Tartara
-- non-empty error messages.
134 2d1c753d Michele Tartara
computeStatus :: DRBDStatus -> DCStatus
135 2d1c753d Michele Tartara
computeStatus (DRBDStatus _ devInfos) =
136 2d1c753d Michele Tartara
  let statuses = map computeDevStatus devInfos
137 2d1c753d Michele Tartara
      (code, strList) = foldr mergeStatuses (DCSCOk, [""]) statuses
138 2d1c753d Michele Tartara
  in DCStatus code $ intercalate "\n" strList
139 2d1c753d Michele Tartara
140 2d1c753d Michele Tartara
-- | Helper function for merging statuses.
141 2d1c753d Michele Tartara
mergeStatuses :: (DCStatusCode, String) -> (DCStatusCode, [String])
142 2d1c753d Michele Tartara
              -> (DCStatusCode, [String])
143 2d1c753d Michele Tartara
mergeStatuses (newStat, newStr) (storedStat, storedStrs) =
144 2d1c753d Michele Tartara
  let resStat = max newStat storedStat
145 2d1c753d Michele Tartara
      resStrs =
146 2d1c753d Michele Tartara
        if newStr == ""
147 2d1c753d Michele Tartara
          then storedStrs
148 2d1c753d Michele Tartara
          else storedStrs ++ [newStr]
149 2d1c753d Michele Tartara
  in (resStat, resStrs)
150 2d1c753d Michele Tartara
151 2d1c753d Michele Tartara
-- | Compute the status of a DRBD device and its error message.
152 2d1c753d Michele Tartara
computeDevStatus :: DeviceInfo -> (DCStatusCode, String)
153 2d1c753d Michele Tartara
computeDevStatus (UnconfiguredDevice _) = (DCSCOk, "")
154 2d1c753d Michele Tartara
computeDevStatus dev =
155 2d1c753d Michele Tartara
  let errMsg s = show (minorNumber dev) ++ ": " ++ s
156 2d1c753d Michele Tartara
      compute_helper StandAlone =
157 2d1c753d Michele Tartara
        (DCSCBad, errMsg "No network config available")
158 2d1c753d Michele Tartara
      compute_helper Disconnecting =
159 2d1c753d Michele Tartara
        (DCSCBad, errMsg "The peer is being disconnected")
160 2d1c753d Michele Tartara
      compute_helper Unconnected =
161 2d1c753d Michele Tartara
        (DCSCTempBad, errMsg "Trying to establish a network connection")
162 2d1c753d Michele Tartara
      compute_helper Timeout =
163 2d1c753d Michele Tartara
        (DCSCTempBad, errMsg "Communication problems between the peers")
164 2d1c753d Michele Tartara
      compute_helper BrokenPipe =
165 2d1c753d Michele Tartara
        (DCSCTempBad, errMsg "Communication problems between the peers")
166 2d1c753d Michele Tartara
      compute_helper NetworkFailure =
167 2d1c753d Michele Tartara
        (DCSCTempBad, errMsg "Communication problems between the peers")
168 2d1c753d Michele Tartara
      compute_helper ProtocolError =
169 2d1c753d Michele Tartara
        (DCSCTempBad, errMsg "Communication problems between the peers")
170 2d1c753d Michele Tartara
      compute_helper TearDown =
171 2d1c753d Michele Tartara
        (DCSCBad, errMsg "The peer is closing the connection")
172 2d1c753d Michele Tartara
      compute_helper WFConnection =
173 2d1c753d Michele Tartara
        (DCSCTempBad, errMsg "Trying to establish a network connection")
174 2d1c753d Michele Tartara
      compute_helper WFReportParams =
175 2d1c753d Michele Tartara
        (DCSCTempBad, errMsg "Trying to establish a network connection")
176 2d1c753d Michele Tartara
      compute_helper Connected = (DCSCOk, "")
177 2d1c753d Michele Tartara
      compute_helper StartingSyncS = (DCSCOk, "")
178 2d1c753d Michele Tartara
      compute_helper StartingSyncT = (DCSCOk, "")
179 2d1c753d Michele Tartara
      compute_helper WFBitMapS = (DCSCOk, "")
180 2d1c753d Michele Tartara
      compute_helper WFBitMapT = (DCSCOk, "")
181 2d1c753d Michele Tartara
      compute_helper WFSyncUUID = (DCSCOk, "")
182 2d1c753d Michele Tartara
      compute_helper SyncSource = (DCSCOk, "")
183 2d1c753d Michele Tartara
      compute_helper SyncTarget = (DCSCOk, "")
184 2d1c753d Michele Tartara
      compute_helper PausedSyncS = (DCSCOk, "")
185 2d1c753d Michele Tartara
      compute_helper PausedSyncT = (DCSCOk, "")
186 2d1c753d Michele Tartara
      compute_helper VerifyS = (DCSCOk, "")
187 2d1c753d Michele Tartara
      compute_helper VerifyT = (DCSCOk, "")
188 2d1c753d Michele Tartara
      compute_helper Unconfigured = (DCSCOk, "")
189 2d1c753d Michele Tartara
  in compute_helper $ connectionState dev
190 2d1c753d Michele Tartara
191 8c5419ee Michele Tartara
-- | This function computes the JSON representation of the DRBD status.
192 8c5419ee Michele Tartara
buildJsonReport :: FilePath -> Maybe FilePath -> IO J.JSValue
193 8c5419ee Michele Tartara
buildJsonReport statusFile pairingFile = do
194 332b1340 Michele Tartara
  contents <-
195 e71c47d3 Michele Tartara
    ((E.try $ readFile statusFile) :: IO (Either IOError String)) >>=
196 638e0a6f Iustin Pop
      exitIfBad "reading from file" . either (BT.Bad . show) BT.Ok
197 e71c47d3 Michele Tartara
  pairingResult <- getPairingInfo pairingFile
198 d78970ba Michele Tartara
  pairing <- exitIfBad "Can't get pairing info" pairingResult
199 2d1c753d Michele Tartara
  drbdData <-
200 2d1c753d Michele Tartara
    case A.parse (drbdStatusParser pairing) $ pack contents of
201 2d1c753d Michele Tartara
      A.Fail unparsedText contexts errorMessage -> exitErr $
202 2d1c753d Michele Tartara
        show (Prelude.take defaultCharNum $ unpack unparsedText) ++ "\n"
203 2d1c753d Michele Tartara
          ++ show contexts ++ "\n" ++ errorMessage
204 2d1c753d Michele Tartara
      A.Done _ drbdS -> return drbdS
205 2d1c753d Michele Tartara
  let status = computeStatus drbdData
206 2d1c753d Michele Tartara
  return . addStatus status $ J.showJSON drbdData
207 e71c47d3 Michele Tartara
208 75706f3a Michele Tartara
-- | This function computes the DCReport for the DRBD status.
209 75706f3a Michele Tartara
buildDCReport :: FilePath -> Maybe FilePath -> IO DCReport
210 75706f3a Michele Tartara
buildDCReport statusFile pairingFile =
211 75706f3a Michele Tartara
  buildJsonReport statusFile pairingFile >>=
212 75706f3a Michele Tartara
    buildReport dcName dcVersion dcFormatVersion dcCategory dcKind
213 75706f3a Michele Tartara
214 e71c47d3 Michele Tartara
-- | Main function.
215 e71c47d3 Michele Tartara
main :: Options -> [String] -> IO ()
216 e71c47d3 Michele Tartara
main opts args = do
217 e71c47d3 Michele Tartara
  let statusFile = fromMaybe defaultFile $ optDrbdStatus opts
218 e71c47d3 Michele Tartara
      pairingFile = optDrbdPairing opts
219 e71c47d3 Michele Tartara
  unless (null args) . exitErr $ "This program takes exactly zero" ++
220 e71c47d3 Michele Tartara
                                  " arguments, got '" ++ unwords args ++ "'"
221 75706f3a Michele Tartara
  report <- buildDCReport statusFile pairingFile
222 e71c47d3 Michele Tartara
  putStrLn $ J.encode report