Statistics
| Branch: | Tag: | Revision:

root / htools / hail.hs @ cc532bdd

History | View | Annotate | Download (3.9 kB)

1
{-| Solver for N+1 cluster errors
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

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

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

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

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

    
109
  request <- readRequest opts args
110

    
111
  let Request rq cdata = request
112

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

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

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

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