Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / HTools / ExtLoader.hs @ 61bbbed7

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 e8f89bb6 Iustin Pop
    ( loadExternalData
32 017a0c3d Iustin Pop
    , commonSuffix
33 4188449c Iustin Pop
    , maybeSaveData
34 e8f89bb6 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 e8f89bb6 Iustin Pop
import System
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 ca848e2a Iustin Pop
    case sepSplit ' ' line of
62 ca848e2a Iustin Pop
      [name, cpu, mem, dsk, net] ->
63 ca848e2a Iustin Pop
          do
64 ca848e2a Iustin Pop
            rcpu <- tryRead name cpu
65 ca848e2a Iustin Pop
            rmem <- tryRead name mem
66 ca848e2a Iustin Pop
            rdsk <- tryRead name dsk
67 ca848e2a Iustin Pop
            rnet <- tryRead name net
68 ca848e2a Iustin Pop
            let du = DynUtil { cpuWeight = rcpu, memWeight = rmem
69 ca848e2a Iustin Pop
                             , dskWeight = rdsk, netWeight = rnet }
70 ca848e2a Iustin Pop
            return (name, du)
71 ca848e2a 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 aa8d2e71 Iustin Pop
  util_contents <- (case optDynuFile opts of
99 aa8d2e71 Iustin Pop
                      Just path -> readFile path
100 aa8d2e71 Iustin Pop
                      Nothing -> return "")
101 aa8d2e71 Iustin Pop
  let util_data = mapM parseUtilisation $ lines util_contents
102 aa8d2e71 Iustin Pop
  util_data' <- (case util_data of
103 aa8d2e71 Iustin Pop
                   Ok x -> return x
104 aa8d2e71 Iustin Pop
                   Bad y -> do
105 aa8d2e71 Iustin Pop
                     hPutStrLn stderr ("Error: can't parse utilisation" ++
106 aa8d2e71 Iustin Pop
                                       " data: " ++ show y)
107 aa8d2e71 Iustin Pop
                     exitWith $ ExitFailure 1)
108 e8f89bb6 Iustin Pop
  input_data <-
109 e8f89bb6 Iustin Pop
      case () of
110 c478f837 Iustin Pop
        _ | setRapi -> wrapIO $ Rapi.loadData mhost
111 e8f89bb6 Iustin Pop
          | setLuxi -> wrapIO $ Luxi.loadData $ fromJust lsock
112 9983063b Iustin Pop
          | setSim -> Simu.loadData simdata
113 16c2369c Iustin Pop
          | setFile -> wrapIO $ Text.loadData $ fromJust tfile
114 16c2369c Iustin Pop
          | otherwise -> return $ Bad "No backend selected! Exiting."
115 e8f89bb6 Iustin Pop
116 2d1708e0 Guido Trotter
  let ldresult = input_data >>= mergeData util_data' exTags selInsts exInsts
117 017a0c3d Iustin Pop
  cdata <-
118 e8f89bb6 Iustin Pop
      (case ldresult of
119 e8f89bb6 Iustin Pop
         Ok x -> return x
120 e8f89bb6 Iustin Pop
         Bad s -> do
121 6a062ff9 Iustin Pop
           hPrintf stderr
122 6a062ff9 Iustin Pop
             "Error: failed to load data, aborting. Details:\n%s\n" s:: IO ()
123 e8f89bb6 Iustin Pop
           exitWith $ ExitFailure 1
124 e8f89bb6 Iustin Pop
      )
125 017a0c3d Iustin Pop
  let (fix_msgs, nl) = checkData (cdNodes cdata) (cdInstances cdata)
126 e8f89bb6 Iustin Pop
127 8cd36391 Iustin Pop
  unless (optVerbose opts == 0) $ maybeShowWarnings fix_msgs
128 e8f89bb6 Iustin Pop
129 017a0c3d Iustin Pop
  return cdata {cdNodes = nl}
130 4188449c Iustin Pop
131 4188449c Iustin Pop
-- | Function to save the cluster data to a file.
132 4188449c Iustin Pop
maybeSaveData :: Maybe FilePath -- ^ The file prefix to save to
133 4188449c Iustin Pop
              -> String         -- ^ The suffix (extension) to add
134 4188449c Iustin Pop
              -> String         -- ^ Informational message
135 4188449c Iustin Pop
              -> ClusterData    -- ^ The cluster data
136 4188449c Iustin Pop
              -> IO ()
137 4188449c Iustin Pop
maybeSaveData Nothing _ _ _ = return ()
138 4188449c Iustin Pop
maybeSaveData (Just path) ext msg cdata = do
139 4188449c Iustin Pop
  let adata = Text.serializeCluster cdata
140 4188449c Iustin Pop
      out_path = path <.> ext
141 4188449c Iustin Pop
  writeFile out_path adata
142 4188449c Iustin Pop
  hPrintf stderr "The cluster state %s has been written to file '%s'\n"
143 4188449c Iustin Pop
          msg out_path