Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / DataCollectors / Drbd.hs @ d78970ba

History | View | Annotate | Download (3.7 kB)

1
{-| DRBD data collector.
2

    
3
-}
4

    
5
{-
6

    
7
Copyright (C) 2012 Google Inc.
8

    
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
13

    
14
This program is distributed in the hope that it will be useful, but
15
WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
General Public License for more details.
18

    
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
02110-1301, USA.
23

    
24
-}
25

    
26
module Ganeti.DataCollectors.Drbd
27
  ( main
28
  , options
29
  , arguments
30
  ) where
31

    
32

    
33
import qualified Control.Exception as E
34
import Control.Monad
35
import Data.Attoparsec.Text.Lazy as A
36
import Data.Maybe
37
import Data.Text.Lazy (pack, unpack)
38
import Network.BSD (getHostName)
39
import qualified Text.JSON as J
40

    
41
import qualified Ganeti.BasicTypes as BT
42
import qualified Ganeti.Constants as C
43
import Ganeti.Block.Drbd.Parser(drbdStatusParser)
44
import Ganeti.Block.Drbd.Types(DrbdInstMinor)
45
import Ganeti.Common
46
import Ganeti.Confd.Client
47
import Ganeti.Confd.Types
48
import Ganeti.DataCollectors.CLI
49
import Ganeti.Utils
50

    
51

    
52
-- | The default path of the DRBD status file.
53
-- It is hardcoded because it is not likely to change.
54
defaultFile :: FilePath
55
defaultFile = C.drbdStatusFile
56

    
57
-- | The default setting for the maximum amount of not parsed character to
58
-- print in case of error.
59
-- It is set to use most of the screen estate on a standard 80x25 terminal.
60
-- TODO: add the possibility to set this with a command line parameter.
61
defaultCharNum :: Int
62
defaultCharNum = 80*20
63

    
64
options :: IO [OptType]
65
options =
66
  return
67
    [ oDrbdStatus
68
    , oDrbdPairing
69
    ]
70

    
71
-- | The list of arguments supported by the program.
72
arguments :: [ArgCompletion]
73
arguments = [ArgCompletion OptComplFile 0 (Just 0)]
74

    
75
-- * Command line options
76

    
77
-- | Get information about the pairing of DRBD minors and Ganeti instances
78
-- on the current node. The information is taken from the Confd client
79
-- or, if a filename is specified, from a JSON encoded file (for testing
80
-- purposes).
81
getPairingInfo :: Maybe String -> IO (BT.Result [DrbdInstMinor])
82
getPairingInfo Nothing = do
83
  curNode <- getHostName
84
  client <- getConfdClient
85
  reply <- query client ReqNodeDrbd $ PlainQuery curNode
86
  return $
87
    case fmap (J.readJSONs . confdReplyAnswer) reply of
88
      Just (J.Ok instMinor) -> BT.Ok instMinor
89
      Just (J.Error msg) -> BT.Bad msg
90
      Nothing -> BT.Bad "No answer from the Confd server"
91
getPairingInfo (Just filename) = do
92
  content <- readFile filename
93
  return $
94
    case J.decode content of
95
      J.Ok instMinor -> BT.Ok instMinor
96
      J.Error msg -> BT.Bad msg
97

    
98
-- | Main function.
99
main :: Options -> [String] -> IO ()
100
main opts args = do
101
  let proc_drbd = fromMaybe defaultFile $ optDrbdStatus opts
102
      instMinor = optDrbdPairing opts
103
  unless (null args) . exitErr $ "This program takes exactly zero" ++
104
                                  " arguments, got '" ++ unwords args ++ "'"
105
  contents <-
106
    ((E.try $ readFile proc_drbd) :: IO (Either IOError String)) >>=
107
      exitIfBad "reading from file" . either (BT.Bad . show) BT.Ok
108
  pairingResult <- getPairingInfo instMinor
109
  pairing <- exitIfBad "Can't get pairing info" pairingResult
110
  output <-
111
    case A.parse (drbdStatusParser pairing) $ pack contents of
112
      A.Fail unparsedText contexts errorMessage -> exitErr $
113
        show (Prelude.take defaultCharNum $ unpack unparsedText) ++ "\n"
114
          ++ show contexts ++ "\n" ++ errorMessage
115
      A.Done _ drbdStatus -> return $ J.encode drbdStatus
116
  putStrLn output