Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / ExtLoader.hs @ c3f8cb12

History | View | Annotate | Download (4.7 kB)

1 525bfb36 Iustin Pop
{-| External data loader.
2 e8f89bb6 Iustin Pop
3 e8f89bb6 Iustin Pop
This module holds the external data loading, and thus is the only one
4 cf924b6d Iustin Pop
depending (via the specialized Text\/Rapi\/Luxi modules) on the actual
5 e8f89bb6 Iustin Pop
libraries implementing the low-level protocols.
6 e8f89bb6 Iustin Pop
7 e8f89bb6 Iustin Pop
-}
8 e8f89bb6 Iustin Pop
9 e8f89bb6 Iustin Pop
{-
10 e8f89bb6 Iustin Pop
11 c478f837 Iustin Pop
Copyright (C) 2009, 2010, 2011 Google Inc.
12 e8f89bb6 Iustin Pop
13 e8f89bb6 Iustin Pop
This program is free software; you can redistribute it and/or modify
14 e8f89bb6 Iustin Pop
it under the terms of the GNU General Public License as published by
15 e8f89bb6 Iustin Pop
the Free Software Foundation; either version 2 of the License, or
16 e8f89bb6 Iustin Pop
(at your option) any later version.
17 e8f89bb6 Iustin Pop
18 e8f89bb6 Iustin Pop
This program is distributed in the hope that it will be useful, but
19 e8f89bb6 Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
20 e8f89bb6 Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21 e8f89bb6 Iustin Pop
General Public License for more details.
22 e8f89bb6 Iustin Pop
23 e8f89bb6 Iustin Pop
You should have received a copy of the GNU General Public License
24 e8f89bb6 Iustin Pop
along with this program; if not, write to the Free Software
25 e8f89bb6 Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 e8f89bb6 Iustin Pop
02110-1301, USA.
27 e8f89bb6 Iustin Pop
28 e8f89bb6 Iustin Pop
-}
29 e8f89bb6 Iustin Pop
30 e8f89bb6 Iustin Pop
module Ganeti.HTools.ExtLoader
31 ebf38064 Iustin Pop
  ( loadExternalData
32 ebf38064 Iustin Pop
  , commonSuffix
33 ebf38064 Iustin Pop
  , maybeSaveData
34 ebf38064 Iustin Pop
  ) where
35 e8f89bb6 Iustin Pop
36 cc532bdd Iustin Pop
import Control.Monad
37 e8f89bb6 Iustin Pop
import Data.Maybe (isJust, fromJust)
38 4188449c Iustin Pop
import System.FilePath
39 e8f89bb6 Iustin Pop
import System.IO
40 7345b69b Iustin Pop
import System.Exit
41 8cd36391 Iustin Pop
import Text.Printf (hPrintf)
42 e8f89bb6 Iustin Pop
43 e8f89bb6 Iustin Pop
import qualified Ganeti.HTools.Luxi as Luxi
44 e8f89bb6 Iustin Pop
import qualified Ganeti.HTools.Rapi as Rapi
45 e8f89bb6 Iustin Pop
import qualified Ganeti.HTools.Simu as Simu
46 e8f89bb6 Iustin Pop
import qualified Ganeti.HTools.Text as Text
47 017a0c3d Iustin Pop
import Ganeti.HTools.Loader (mergeData, checkData, ClusterData(..)
48 017a0c3d Iustin Pop
                            , commonSuffix)
49 e8f89bb6 Iustin Pop
50 e8f89bb6 Iustin Pop
import Ganeti.HTools.Types
51 e8f89bb6 Iustin Pop
import Ganeti.HTools.CLI
52 aa8d2e71 Iustin Pop
import Ganeti.HTools.Utils (sepSplit, tryRead)
53 e8f89bb6 Iustin Pop
54 525bfb36 Iustin Pop
-- | Error beautifier.
55 e8f89bb6 Iustin Pop
wrapIO :: IO (Result a) -> IO (Result a)
56 1cf97474 Iustin Pop
wrapIO = flip catch (return . Bad . show)
57 e8f89bb6 Iustin Pop
58 179c0828 Iustin Pop
-- | Parses a user-supplied utilisation string.
59 aa8d2e71 Iustin Pop
parseUtilisation :: String -> Result (String, DynUtil)
60 aa8d2e71 Iustin Pop
parseUtilisation line =
61 ebf38064 Iustin Pop
  case sepSplit ' ' line of
62 ebf38064 Iustin Pop
    [name, cpu, mem, dsk, net] ->
63 ebf38064 Iustin Pop
      do
64 ebf38064 Iustin Pop
        rcpu <- tryRead name cpu
65 ebf38064 Iustin Pop
        rmem <- tryRead name mem
66 ebf38064 Iustin Pop
        rdsk <- tryRead name dsk
67 ebf38064 Iustin Pop
        rnet <- tryRead name net
68 ebf38064 Iustin Pop
        let du = DynUtil { cpuWeight = rcpu, memWeight = rmem
69 ebf38064 Iustin Pop
                         , dskWeight = rdsk, netWeight = rnet }
70 ebf38064 Iustin Pop
        return (name, du)
71 ebf38064 Iustin Pop
    _ -> Bad $ "Cannot parse line " ++ line
72 aa8d2e71 Iustin Pop
73 e8f89bb6 Iustin Pop
-- | External tool data loader from a variety of sources.
74 e8f89bb6 Iustin Pop
loadExternalData :: Options
75 017a0c3d Iustin Pop
                 -> IO ClusterData
76 e8f89bb6 Iustin Pop
loadExternalData opts = do
77 16c2369c Iustin Pop
  let mhost = optMaster opts
78 e8f89bb6 Iustin Pop
      lsock = optLuxi opts
79 16c2369c Iustin Pop
      tfile = optDataFile opts
80 e8f89bb6 Iustin Pop
      simdata = optNodeSim opts
81 e8f89bb6 Iustin Pop
      setRapi = mhost /= ""
82 e8f89bb6 Iustin Pop
      setLuxi = isJust lsock
83 9983063b Iustin Pop
      setSim = (not . null) simdata
84 16c2369c Iustin Pop
      setFile = isJust tfile
85 16c2369c Iustin Pop
      allSet = filter id [setRapi, setLuxi, setFile]
86 0f15cc76 Iustin Pop
      exTags = case optExTags opts of
87 0f15cc76 Iustin Pop
                 Nothing -> []
88 0f15cc76 Iustin Pop
                 Just etl -> map (++ ":") etl
89 2d1708e0 Guido Trotter
      selInsts = optSelInst opts
90 39f979b8 Iustin Pop
      exInsts = optExInst opts
91 0f15cc76 Iustin Pop
92 e8f89bb6 Iustin Pop
  when (length allSet > 1) $
93 e8f89bb6 Iustin Pop
       do
94 45ab6a8d Iustin Pop
         hPutStrLn stderr ("Error: Only one of the rapi, luxi, and data" ++
95 45ab6a8d Iustin Pop
                           " files options should be given.")
96 e8f89bb6 Iustin Pop
         exitWith $ ExitFailure 1
97 e8f89bb6 Iustin Pop
98 3603605a Iustin Pop
  util_contents <- maybe (return "") readFile (optDynuFile opts)
99 aa8d2e71 Iustin Pop
  let util_data = mapM parseUtilisation $ lines util_contents
100 3603605a Iustin Pop
  util_data' <- case util_data of
101 3603605a Iustin Pop
                  Ok x  -> return x
102 3603605a Iustin Pop
                  Bad y -> do
103 3603605a Iustin Pop
                    hPutStrLn stderr ("Error: can't parse utilisation" ++
104 3603605a Iustin Pop
                                      " data: " ++ show y)
105 3603605a Iustin Pop
                    exitWith $ ExitFailure 1
106 e8f89bb6 Iustin Pop
  input_data <-
107 ebf38064 Iustin Pop
    case () of
108 ebf38064 Iustin Pop
      _ | setRapi -> wrapIO $ Rapi.loadData mhost
109 ebf38064 Iustin Pop
        | setLuxi -> wrapIO $ Luxi.loadData $ fromJust lsock
110 ebf38064 Iustin Pop
        | setSim -> Simu.loadData simdata
111 ebf38064 Iustin Pop
        | setFile -> wrapIO $ Text.loadData $ fromJust tfile
112 ebf38064 Iustin Pop
        | otherwise -> return $ Bad "No backend selected! Exiting."
113 e8f89bb6 Iustin Pop
114 2d1708e0 Guido Trotter
  let ldresult = input_data >>= mergeData util_data' exTags selInsts exInsts
115 017a0c3d Iustin Pop
  cdata <-
116 3603605a Iustin Pop
    case ldresult of
117 3603605a Iustin Pop
      Ok x -> return x
118 3603605a Iustin Pop
      Bad s -> do
119 3603605a Iustin Pop
        hPrintf stderr
120 3603605a Iustin Pop
          "Error: failed to load data, aborting. Details:\n%s\n" s:: IO ()
121 3603605a Iustin Pop
        exitWith $ ExitFailure 1
122 017a0c3d Iustin Pop
  let (fix_msgs, nl) = checkData (cdNodes cdata) (cdInstances cdata)
123 e8f89bb6 Iustin Pop
124 8cd36391 Iustin Pop
  unless (optVerbose opts == 0) $ maybeShowWarnings fix_msgs
125 e8f89bb6 Iustin Pop
126 017a0c3d Iustin Pop
  return cdata {cdNodes = nl}
127 4188449c Iustin Pop
128 4188449c Iustin Pop
-- | Function to save the cluster data to a file.
129 4188449c Iustin Pop
maybeSaveData :: Maybe FilePath -- ^ The file prefix to save to
130 4188449c Iustin Pop
              -> String         -- ^ The suffix (extension) to add
131 4188449c Iustin Pop
              -> String         -- ^ Informational message
132 4188449c Iustin Pop
              -> ClusterData    -- ^ The cluster data
133 4188449c Iustin Pop
              -> IO ()
134 4188449c Iustin Pop
maybeSaveData Nothing _ _ _ = return ()
135 4188449c Iustin Pop
maybeSaveData (Just path) ext msg cdata = do
136 4188449c Iustin Pop
  let adata = Text.serializeCluster cdata
137 4188449c Iustin Pop
      out_path = path <.> ext
138 4188449c Iustin Pop
  writeFile out_path adata
139 4188449c Iustin Pop
  hPrintf stderr "The cluster state %s has been written to file '%s'\n"
140 4188449c Iustin Pop
          msg out_path