Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / DataCollectors / Lv.hs @ 820ca72d

History | View | Annotate | Download (6 kB)

1 1a9d864c Michele Tartara
{-| Logical Volumes data collector.
2 1a9d864c Michele Tartara
3 1a9d864c Michele Tartara
-}
4 1a9d864c Michele Tartara
5 1a9d864c Michele Tartara
{-
6 1a9d864c Michele Tartara
7 1a9d864c Michele Tartara
Copyright (C) 2013 Google Inc.
8 1a9d864c Michele Tartara
9 1a9d864c Michele Tartara
This program is free software; you can redistribute it and/or modify
10 1a9d864c Michele Tartara
it under the terms of the GNU General Public License as published by
11 1a9d864c Michele Tartara
the Free Software Foundation; either version 2 of the License, or
12 1a9d864c Michele Tartara
(at your option) any later version.
13 1a9d864c Michele Tartara
14 1a9d864c Michele Tartara
This program is distributed in the hope that it will be useful, but
15 1a9d864c Michele Tartara
WITHOUT ANY WARRANTY; without even the implied warranty of
16 1a9d864c Michele Tartara
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 1a9d864c Michele Tartara
General Public License for more details.
18 1a9d864c Michele Tartara
19 1a9d864c Michele Tartara
You should have received a copy of the GNU General Public License
20 1a9d864c Michele Tartara
along with this program; if not, write to the Free Software
21 1a9d864c Michele Tartara
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 1a9d864c Michele Tartara
02110-1301, USA.
23 1a9d864c Michele Tartara
24 1a9d864c Michele Tartara
-}
25 1a9d864c Michele Tartara
26 1a9d864c Michele Tartara
module Ganeti.DataCollectors.Lv
27 1a9d864c Michele Tartara
  ( main
28 1a9d864c Michele Tartara
  , options
29 1a9d864c Michele Tartara
  , arguments
30 1a9d864c Michele Tartara
  , dcName
31 1a9d864c Michele Tartara
  , dcVersion
32 1a9d864c Michele Tartara
  , dcFormatVersion
33 1a9d864c Michele Tartara
  , dcCategory
34 1a9d864c Michele Tartara
  , dcKind
35 1a9d864c Michele Tartara
  , dcReport
36 1a9d864c Michele Tartara
  ) where
37 1a9d864c Michele Tartara
38 1a9d864c Michele Tartara
39 1a9d864c Michele Tartara
import qualified Control.Exception as E
40 1a9d864c Michele Tartara
import Control.Monad
41 1a9d864c Michele Tartara
import Data.Attoparsec.Text.Lazy as A
42 820ca72d Michele Tartara
import Data.List
43 1a9d864c Michele Tartara
import Data.Text.Lazy (pack, unpack)
44 820ca72d Michele Tartara
import Network.BSD (getHostName)
45 1a9d864c Michele Tartara
import System.Process
46 1a9d864c Michele Tartara
import qualified Text.JSON as J
47 1a9d864c Michele Tartara
48 1a9d864c Michele Tartara
import qualified Ganeti.BasicTypes as BT
49 1a9d864c Michele Tartara
import Ganeti.Common
50 820ca72d Michele Tartara
import Ganeti.Confd.ClientFunctions
51 1a9d864c Michele Tartara
import Ganeti.DataCollectors.CLI
52 1a9d864c Michele Tartara
import Ganeti.DataCollectors.Types
53 820ca72d Michele Tartara
import Ganeti.JSON
54 820ca72d Michele Tartara
import Ganeti.Objects
55 1a9d864c Michele Tartara
import Ganeti.Storage.Lvm.LVParser
56 f22b987a Michele Tartara
import Ganeti.Storage.Lvm.Types
57 1a9d864c Michele Tartara
import Ganeti.Utils
58 1a9d864c Michele Tartara
59 1a9d864c Michele Tartara
60 1a9d864c Michele Tartara
-- | The default setting for the maximum amount of not parsed character to
61 1a9d864c Michele Tartara
-- print in case of error.
62 1a9d864c Michele Tartara
-- It is set to use most of the screen estate on a standard 80x25 terminal.
63 1a9d864c Michele Tartara
-- TODO: add the possibility to set this with a command line parameter.
64 1a9d864c Michele Tartara
defaultCharNum :: Int
65 1a9d864c Michele Tartara
defaultCharNum = 80*20
66 1a9d864c Michele Tartara
67 1a9d864c Michele Tartara
-- | The name of this data collector.
68 1a9d864c Michele Tartara
dcName :: String
69 1a9d864c Michele Tartara
dcName = "lv"
70 1a9d864c Michele Tartara
71 1a9d864c Michele Tartara
-- | The version of this data collector.
72 1a9d864c Michele Tartara
dcVersion :: DCVersion
73 1a9d864c Michele Tartara
dcVersion = DCVerBuiltin
74 1a9d864c Michele Tartara
75 1a9d864c Michele Tartara
-- | The version number for the data format of this data collector.
76 1a9d864c Michele Tartara
dcFormatVersion :: Int
77 1a9d864c Michele Tartara
dcFormatVersion = 1
78 1a9d864c Michele Tartara
79 1a9d864c Michele Tartara
-- | The category of this data collector.
80 1a9d864c Michele Tartara
dcCategory :: Maybe DCCategory
81 1a9d864c Michele Tartara
dcCategory = Just DCStorage
82 1a9d864c Michele Tartara
83 1a9d864c Michele Tartara
-- | The kind of this data collector.
84 1a9d864c Michele Tartara
dcKind :: DCKind
85 1a9d864c Michele Tartara
dcKind = DCKPerf
86 1a9d864c Michele Tartara
87 1a9d864c Michele Tartara
-- | The data exported by the data collector, taken from the default location.
88 1a9d864c Michele Tartara
dcReport :: IO DCReport
89 820ca72d Michele Tartara
dcReport = buildDCReport defaultOptions
90 1a9d864c Michele Tartara
91 1a9d864c Michele Tartara
-- * Command line options
92 1a9d864c Michele Tartara
93 1a9d864c Michele Tartara
options :: IO [OptType]
94 1a9d864c Michele Tartara
options =
95 1a9d864c Michele Tartara
  return
96 1a9d864c Michele Tartara
    [ oInputFile
97 820ca72d Michele Tartara
    , oConfdAddr
98 820ca72d Michele Tartara
    , oConfdPort
99 820ca72d Michele Tartara
    , oInstances
100 1a9d864c Michele Tartara
    ]
101 1a9d864c Michele Tartara
102 1a9d864c Michele Tartara
-- | The list of arguments supported by the program.
103 1a9d864c Michele Tartara
arguments :: [ArgCompletion]
104 1a9d864c Michele Tartara
arguments = [ArgCompletion OptComplFile 0 (Just 0)]
105 1a9d864c Michele Tartara
106 f22b987a Michele Tartara
-- | Get information about logical volumes from file (if specified) or
107 f22b987a Michele Tartara
-- by actually running the command to get it from a live cluster.
108 f22b987a Michele Tartara
getLvInfo :: Maybe FilePath -> IO [LVInfo]
109 f22b987a Michele Tartara
getLvInfo inputFile = do
110 f5d84060 Michele Tartara
  let cmd = lvCommand
111 f5d84060 Michele Tartara
      params = lvParams
112 1a9d864c Michele Tartara
      fromLvs =
113 1a9d864c Michele Tartara
        ((E.try $ readProcess cmd params "") :: IO (Either IOError String)) >>=
114 820ca72d Michele Tartara
        exitIfBad "running command" . either (BT.Bad . show) BT.Ok
115 1a9d864c Michele Tartara
  contents <-
116 1a9d864c Michele Tartara
    maybe fromLvs (\fn -> ((E.try $ readFile fn) :: IO (Either IOError String))
117 1a9d864c Michele Tartara
      >>= exitIfBad "reading from file" . either (BT.Bad . show) BT.Ok)
118 1a9d864c Michele Tartara
      inputFile
119 f22b987a Michele Tartara
  case A.parse lvParser $ pack contents of
120 f22b987a Michele Tartara
    A.Fail unparsedText contexts errorMessage -> exitErr $
121 f22b987a Michele Tartara
      show (Prelude.take defaultCharNum $ unpack unparsedText) ++ "\n"
122 f22b987a Michele Tartara
        ++ show contexts ++ "\n" ++ errorMessage
123 f22b987a Michele Tartara
    A.Done _ lvinfoD -> return lvinfoD
124 f22b987a Michele Tartara
125 820ca72d Michele Tartara
-- | Get the list of instances on the current node (both primary and secondary)
126 820ca72d Michele Tartara
-- either from a provided file or by querying Confd.
127 820ca72d Michele Tartara
getInstanceList :: Options -> IO ([Instance], [Instance])
128 820ca72d Michele Tartara
getInstanceList opts = do
129 820ca72d Michele Tartara
  let srvAddr = optConfdAddr opts
130 820ca72d Michele Tartara
      srvPort = optConfdPort opts
131 820ca72d Michele Tartara
      instFile = optInstances opts
132 820ca72d Michele Tartara
      fromConfdUnchecked :: IO (BT.Result ([Instance], [Instance]))
133 820ca72d Michele Tartara
      fromConfdUnchecked = getHostName >>= \n -> getInstances n srvAddr srvPort
134 820ca72d Michele Tartara
      fromConfd :: IO (BT.Result ([Instance], [Instance]))
135 820ca72d Michele Tartara
      fromConfd =
136 820ca72d Michele Tartara
        liftM (either (BT.Bad . show) id) (E.try fromConfdUnchecked :: 
137 820ca72d Michele Tartara
          IO (Either IOError (BT.Result ([Instance], [Instance]))))
138 820ca72d Michele Tartara
      fromFile :: FilePath -> IO (BT.Result ([Instance], [Instance]))
139 820ca72d Michele Tartara
      fromFile inputFile = do
140 820ca72d Michele Tartara
        contents <-
141 820ca72d Michele Tartara
          ((E.try $ readFile inputFile) :: IO (Either IOError String))
142 820ca72d Michele Tartara
            >>= exitIfBad "reading from file" . either (BT.Bad . show) BT.Ok
143 820ca72d Michele Tartara
        return . fromJResult "Not a list of instances" $ J.decode contents
144 820ca72d Michele Tartara
  instances <- maybe fromConfd fromFile instFile
145 820ca72d Michele Tartara
  exitIfBad "Unable to obtain the list of instances" instances
146 820ca72d Michele Tartara
147 820ca72d Michele Tartara
-- | Adds the name of the instance to the information about one logical volume.
148 820ca72d Michele Tartara
addInstNameToOneLv :: [Instance] -> LVInfo -> LVInfo
149 820ca72d Michele Tartara
addInstNameToOneLv instances lvInfo =
150 820ca72d Michele Tartara
  let vg_name = lviVgName lvInfo
151 820ca72d Michele Tartara
      lv_name = lviName lvInfo
152 820ca72d Michele Tartara
      instanceHasDisk = any (includesLogicalId vg_name lv_name) . instDisks
153 820ca72d Michele Tartara
      rightInstance = find instanceHasDisk instances
154 820ca72d Michele Tartara
    in 
155 820ca72d Michele Tartara
      case rightInstance of
156 820ca72d Michele Tartara
        Nothing -> lvInfo
157 820ca72d Michele Tartara
        Just i -> lvInfo { lviInstance = Just $ instName i }
158 820ca72d Michele Tartara
159 820ca72d Michele Tartara
-- | Adds the name of the instance to the information about logical volumes.
160 820ca72d Michele Tartara
addInstNameToLv :: [Instance] -> [LVInfo] -> [LVInfo]
161 820ca72d Michele Tartara
addInstNameToLv instances = map (addInstNameToOneLv instances)
162 820ca72d Michele Tartara
163 820ca72d Michele Tartara
-- | This function computes the JSON representation of the LV status.
164 820ca72d Michele Tartara
buildJsonReport :: Options -> IO J.JSValue
165 820ca72d Michele Tartara
buildJsonReport opts = do
166 820ca72d Michele Tartara
  let inputFile = optInputFile opts
167 f22b987a Michele Tartara
  lvInfo <- getLvInfo inputFile
168 820ca72d Michele Tartara
  (prim, sec) <- getInstanceList opts
169 820ca72d Michele Tartara
  return . J.showJSON $ addInstNameToLv (prim ++ sec) lvInfo
170 1a9d864c Michele Tartara
171 1a9d864c Michele Tartara
-- | This function computes the DCReport for the logical volumes.
172 820ca72d Michele Tartara
buildDCReport :: Options -> IO DCReport
173 820ca72d Michele Tartara
buildDCReport opts =
174 820ca72d Michele Tartara
  buildJsonReport opts >>=
175 1a9d864c Michele Tartara
    buildReport dcName dcVersion dcFormatVersion dcCategory dcKind
176 1a9d864c Michele Tartara
177 1a9d864c Michele Tartara
-- | Main function.
178 1a9d864c Michele Tartara
main :: Options -> [String] -> IO ()
179 1a9d864c Michele Tartara
main opts args = do
180 1a9d864c Michele Tartara
  unless (null args) . exitErr $ "This program takes exactly zero" ++
181 1a9d864c Michele Tartara
                                 " arguments, got '" ++ unwords args ++ "'"
182 1a9d864c Michele Tartara
183 820ca72d Michele Tartara
  report <- buildDCReport opts
184 1a9d864c Michele Tartara
  putStrLn $ J.encode report