Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (4.9 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 4892d955 René Nussbaumer
import qualified Ganeti.HTools.IAlloc as IAlloc
48 017a0c3d Iustin Pop
import Ganeti.HTools.Loader (mergeData, checkData, ClusterData(..)
49 017a0c3d Iustin Pop
                            , commonSuffix)
50 e8f89bb6 Iustin Pop
51 e8f89bb6 Iustin Pop
import Ganeti.HTools.Types
52 e8f89bb6 Iustin Pop
import Ganeti.HTools.CLI
53 aa8d2e71 Iustin Pop
import Ganeti.HTools.Utils (sepSplit, tryRead)
54 e8f89bb6 Iustin Pop
55 525bfb36 Iustin Pop
-- | Error beautifier.
56 e8f89bb6 Iustin Pop
wrapIO :: IO (Result a) -> IO (Result a)
57 1cf97474 Iustin Pop
wrapIO = flip catch (return . Bad . show)
58 e8f89bb6 Iustin Pop
59 179c0828 Iustin Pop
-- | Parses a user-supplied utilisation string.
60 aa8d2e71 Iustin Pop
parseUtilisation :: String -> Result (String, DynUtil)
61 aa8d2e71 Iustin Pop
parseUtilisation line =
62 ebf38064 Iustin Pop
  case sepSplit ' ' line of
63 ebf38064 Iustin Pop
    [name, cpu, mem, dsk, net] ->
64 ebf38064 Iustin Pop
      do
65 ebf38064 Iustin Pop
        rcpu <- tryRead name cpu
66 ebf38064 Iustin Pop
        rmem <- tryRead name mem
67 ebf38064 Iustin Pop
        rdsk <- tryRead name dsk
68 ebf38064 Iustin Pop
        rnet <- tryRead name net
69 ebf38064 Iustin Pop
        let du = DynUtil { cpuWeight = rcpu, memWeight = rmem
70 ebf38064 Iustin Pop
                         , dskWeight = rdsk, netWeight = rnet }
71 ebf38064 Iustin Pop
        return (name, du)
72 ebf38064 Iustin Pop
    _ -> Bad $ "Cannot parse line " ++ line
73 aa8d2e71 Iustin Pop
74 e8f89bb6 Iustin Pop
-- | External tool data loader from a variety of sources.
75 e8f89bb6 Iustin Pop
loadExternalData :: Options
76 017a0c3d Iustin Pop
                 -> IO ClusterData
77 e8f89bb6 Iustin Pop
loadExternalData opts = do
78 16c2369c Iustin Pop
  let mhost = optMaster opts
79 e8f89bb6 Iustin Pop
      lsock = optLuxi opts
80 16c2369c Iustin Pop
      tfile = optDataFile opts
81 e8f89bb6 Iustin Pop
      simdata = optNodeSim opts
82 4892d955 René Nussbaumer
      iallocsrc = optIAllocSrc opts
83 e8f89bb6 Iustin Pop
      setRapi = mhost /= ""
84 e8f89bb6 Iustin Pop
      setLuxi = isJust lsock
85 9983063b Iustin Pop
      setSim = (not . null) simdata
86 16c2369c Iustin Pop
      setFile = isJust tfile
87 4892d955 René Nussbaumer
      setIAllocSrc = isJust iallocsrc
88 16c2369c Iustin Pop
      allSet = filter id [setRapi, setLuxi, setFile]
89 0f15cc76 Iustin Pop
      exTags = case optExTags opts of
90 0f15cc76 Iustin Pop
                 Nothing -> []
91 0f15cc76 Iustin Pop
                 Just etl -> map (++ ":") etl
92 2d1708e0 Guido Trotter
      selInsts = optSelInst opts
93 39f979b8 Iustin Pop
      exInsts = optExInst opts
94 0f15cc76 Iustin Pop
95 e8f89bb6 Iustin Pop
  when (length allSet > 1) $
96 e8f89bb6 Iustin Pop
       do
97 45ab6a8d Iustin Pop
         hPutStrLn stderr ("Error: Only one of the rapi, luxi, and data" ++
98 45ab6a8d Iustin Pop
                           " files options should be given.")
99 e8f89bb6 Iustin Pop
         exitWith $ ExitFailure 1
100 e8f89bb6 Iustin Pop
101 3603605a Iustin Pop
  util_contents <- maybe (return "") readFile (optDynuFile opts)
102 aa8d2e71 Iustin Pop
  let util_data = mapM parseUtilisation $ lines util_contents
103 3603605a Iustin Pop
  util_data' <- case util_data of
104 3603605a Iustin Pop
                  Ok x  -> return x
105 3603605a Iustin Pop
                  Bad y -> do
106 3603605a Iustin Pop
                    hPutStrLn stderr ("Error: can't parse utilisation" ++
107 3603605a Iustin Pop
                                      " data: " ++ show y)
108 3603605a Iustin Pop
                    exitWith $ ExitFailure 1
109 e8f89bb6 Iustin Pop
  input_data <-
110 ebf38064 Iustin Pop
    case () of
111 ebf38064 Iustin Pop
      _ | setRapi -> wrapIO $ Rapi.loadData mhost
112 ebf38064 Iustin Pop
        | setLuxi -> wrapIO $ Luxi.loadData $ fromJust lsock
113 ebf38064 Iustin Pop
        | setSim -> Simu.loadData simdata
114 ebf38064 Iustin Pop
        | setFile -> wrapIO $ Text.loadData $ fromJust tfile
115 4892d955 René Nussbaumer
        | setIAllocSrc -> wrapIO $ IAlloc.loadData $ fromJust iallocsrc
116 ebf38064 Iustin Pop
        | otherwise -> return $ Bad "No backend selected! Exiting."
117 e8f89bb6 Iustin Pop
118 2d1708e0 Guido Trotter
  let ldresult = input_data >>= mergeData util_data' exTags selInsts exInsts
119 017a0c3d Iustin Pop
  cdata <-
120 3603605a Iustin Pop
    case ldresult of
121 3603605a Iustin Pop
      Ok x -> return x
122 3603605a Iustin Pop
      Bad s -> do
123 3603605a Iustin Pop
        hPrintf stderr
124 3603605a Iustin Pop
          "Error: failed to load data, aborting. Details:\n%s\n" s:: IO ()
125 3603605a Iustin Pop
        exitWith $ ExitFailure 1
126 017a0c3d Iustin Pop
  let (fix_msgs, nl) = checkData (cdNodes cdata) (cdInstances cdata)
127 e8f89bb6 Iustin Pop
128 8cd36391 Iustin Pop
  unless (optVerbose opts == 0) $ maybeShowWarnings fix_msgs
129 e8f89bb6 Iustin Pop
130 017a0c3d Iustin Pop
  return cdata {cdNodes = nl}
131 4188449c Iustin Pop
132 4188449c Iustin Pop
-- | Function to save the cluster data to a file.
133 4188449c Iustin Pop
maybeSaveData :: Maybe FilePath -- ^ The file prefix to save to
134 4188449c Iustin Pop
              -> String         -- ^ The suffix (extension) to add
135 4188449c Iustin Pop
              -> String         -- ^ Informational message
136 4188449c Iustin Pop
              -> ClusterData    -- ^ The cluster data
137 4188449c Iustin Pop
              -> IO ()
138 4188449c Iustin Pop
maybeSaveData Nothing _ _ _ = return ()
139 4188449c Iustin Pop
maybeSaveData (Just path) ext msg cdata = do
140 4188449c Iustin Pop
  let adata = Text.serializeCluster cdata
141 4188449c Iustin Pop
      out_path = path <.> ext
142 4188449c Iustin Pop
  writeFile out_path adata
143 4188449c Iustin Pop
  hPrintf stderr "The cluster state %s has been written to file '%s'\n"
144 4188449c Iustin Pop
          msg out_path