Statistics
| Branch: | Tag: | Revision:

root / htools / hail.hs @ 1fe412bb

History | View | Annotate | Download (4 kB)

1
{-| IAllocator plugin for Ganeti.
2

    
3
-}
4

    
5
{-
6

    
7
Copyright (C) 2009, 2010, 2011 Google Inc.
8

    
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
13

    
14
This program is distributed in the hope that it will be useful, but
15
WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
General Public License for more details.
18

    
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
02110-1301, USA.
23

    
24
-}
25

    
26
module Main (main) where
27

    
28
import Control.Monad
29
import Data.List
30
import Data.Maybe (isJust, fromJust)
31
import System (exitWith, ExitCode(..))
32
import System.IO
33
import qualified System
34

    
35
import qualified Ganeti.HTools.Cluster as Cluster
36

    
37
import Ganeti.HTools.CLI
38
import Ganeti.HTools.IAlloc
39
import Ganeti.HTools.Types
40
import Ganeti.HTools.Loader (RqType(..), Request(..), ClusterData(..))
41
import Ganeti.HTools.ExtLoader (loadExternalData)
42

    
43
-- | Options list and functions
44
options :: [OptType]
45
options =
46
    [ oPrintNodes
47
    , oDataFile
48
    , oNodeSim
49
    , oVerbose
50
    , oShowVer
51
    , oShowHelp
52
    ]
53

    
54
processResults :: (Monad m) =>
55
                  RqType -> Cluster.AllocSolution
56
               -> m Cluster.AllocSolution
57
processResults _ (Cluster.AllocSolution { Cluster.asSolutions = [],
58
                                          Cluster.asLog = msgs }) =
59
  fail $ intercalate ", " msgs
60

    
61
processResults (Evacuate _) as = return as
62

    
63
processResults _ as =
64
    case Cluster.asSolutions as of
65
      _:[] -> return as
66
      _ -> fail "Internal error: multiple allocation solutions"
67

    
68
-- | Process a request and return new node lists
69
processRequest :: Request
70
               -> Result Cluster.AllocSolution
71
processRequest request =
72
  let Request rqtype (ClusterData gl nl il _) = request
73
  in case rqtype of
74
       Allocate xi reqn -> Cluster.tryMGAlloc gl nl il xi reqn
75
       Relocate idx reqn exnodes -> Cluster.tryMGReloc gl nl il
76
                                    idx reqn exnodes
77
       Evacuate exnodes -> Cluster.tryMGEvac gl nl il exnodes
78
       MultiReloc _ _ -> fail "multi-reloc not handled"
79
       NodeEvacuate _ _ -> fail "node-evacuate not handled"
80

    
81
-- | Reads the request from the data file(s)
82
readRequest :: Options -> [String] -> IO Request
83
readRequest opts args = do
84
  when (null args) $ do
85
         hPutStrLn stderr "Error: this program needs an input file."
86
         exitWith $ ExitFailure 1
87

    
88
  input_data <- readFile (head args)
89
  r1 <- case parseData input_data of
90
          Bad err -> do
91
            hPutStrLn stderr $ "Error: " ++ err
92
            exitWith $ ExitFailure 1
93
          Ok rq -> return rq
94
  (if isJust (optDataFile opts) ||  (not . null . optNodeSim) opts
95
   then do
96
     cdata <- loadExternalData opts
97
     let Request rqt _ = r1
98
     return $ Request rqt cdata
99
   else return r1)
100

    
101
-- | Main function.
102
main :: IO ()
103
main = do
104
  cmd_args <- System.getArgs
105
  (opts, args) <- parseOpts cmd_args "hail" options
106

    
107
  let shownodes = optShowNodes opts
108
      verbose = optVerbose opts
109

    
110
  request <- readRequest opts args
111

    
112
  let Request rq cdata = request
113

    
114
  when (verbose > 1) $
115
       hPutStrLn stderr $ "Received request: " ++ show rq
116

    
117
  when (verbose > 2) $
118
       hPutStrLn stderr $ "Received cluster data: " ++ show cdata
119

    
120
  when (isJust shownodes) $ do
121
         hPutStrLn stderr "Initial cluster status:"
122
         hPutStrLn stderr $ Cluster.printNodes (cdNodes cdata)
123
                       (fromJust shownodes)
124

    
125
  let sols = processRequest request >>= processResults rq
126
  let (ok, info, rn) =
127
          case sols of
128
            Ok as -> (True, "Request successful: " ++
129
                            intercalate ", " (Cluster.asLog as),
130
                      Cluster.asSolutions as)
131
            Bad s -> (False, "Request failed: " ++ s, [])
132
      resp = formatResponse ok info rq rn
133
  putStrLn resp