Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / HTools / ExtLoader.hs @ ef947a42

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