Statistics
| Branch: | Tag: | Revision:

root / hail.hs @ 2795466b

History | View | Annotate | Download (4.5 kB)

1
{-| Solver for N+1 cluster errors
2

    
3
-}
4

    
5
{-
6

    
7
Copyright (C) 2009 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 Data.List
29
import Data.Function
30
import Monad
31
import System
32
import System.IO
33
import System.Console.GetOpt
34
import qualified System
35

    
36
import Text.Printf (printf)
37

    
38
import qualified Ganeti.HTools.Cluster as Cluster
39
import qualified Ganeti.HTools.Node as Node
40
import qualified Ganeti.HTools.Instance as Instance
41
import qualified Ganeti.HTools.CLI as CLI
42
import Ganeti.HTools.IAlloc
43
import Ganeti.HTools.Types
44
import Ganeti.HTools.Loader (RqType(..), Request(..))
45

    
46
-- | Command line options structure.
47
data Options = Options
48
    { optShowVer   :: Bool           -- ^ Just show the program version
49
    , optShowHelp  :: Bool           -- ^ Just show the help
50
    } deriving Show
51

    
52
-- | Default values for the command line options.
53
defaultOptions :: Options
54
defaultOptions  = Options
55
 { optShowVer   = False
56
 , optShowHelp  = False
57
 }
58

    
59
instance CLI.CLIOptions Options where
60
    showVersion = optShowVer
61
    showHelp    = optShowHelp
62

    
63
-- | Options list and functions
64
options :: [OptDescr (Options -> Options)]
65
options =
66
    [ Option ['V']     ["version"]
67
      (NoArg (\ opts -> opts { optShowVer = True}))
68
      "show the version of the program"
69
    , Option ['h']     ["help"]
70
      (NoArg (\ opts -> opts { optShowHelp = True}))
71
      "show help"
72
    ]
73

    
74

    
75
filterFails :: (Monad m) => [(OpResult Node.List,
76
                              Instance.Instance, [Node.Node])]
77
            -> m [(Node.List, [Node.Node])]
78
filterFails sols =
79
    if null sols then fail "No nodes onto which to allocate at all"
80
    else let sols' = concatMap (\ (onl, _, nn) ->
81
                                    case onl of
82
                                      OpFail _ -> []
83
                                      OpGood gnl -> [(gnl, nn)]
84
                               ) sols
85
         in
86
           if null sols'
87
           then fail "No valid allocation solutions"
88
           else return sols'
89

    
90
processResults :: (Monad m) => [(Node.List, [Node.Node])]
91
               -> m (String, [Node.Node])
92
processResults sols =
93
    let sols' = map (\(nl', ns) -> (Cluster.compCV  nl', ns)) sols
94
        sols'' = sortBy (compare `on` fst) sols'
95
        (best, w) = head sols''
96
        (worst, l) = last sols''
97
        info = printf "Valid results: %d, best score: %.8f for node(s) %s, \
98
                      \worst score: %.8f for node(s) %s" (length sols'')
99
                      best (intercalate "/" . map Node.name $ w)
100
                      worst (intercalate "/" . map Node.name $ l)::String
101
    in return (info, w)
102

    
103
-- | Process a request and return new node lists
104
processRequest :: Request
105
               -> Result [(OpResult Node.List, Instance.Instance, [Node.Node])]
106
processRequest request =
107
  let Request rqtype nl il _ = request
108
  in case rqtype of
109
       Allocate xi reqn -> Cluster.tryAlloc nl il xi reqn
110
       Relocate idx reqn exnodes -> Cluster.tryReloc nl il idx reqn exnodes
111

    
112
-- | Main function.
113
main :: IO ()
114
main = do
115
  cmd_args <- System.getArgs
116
  (_, args) <- CLI.parseOpts cmd_args "hail" options defaultOptions
117

    
118
  when (null args) $ do
119
         hPutStrLn stderr "Error: this program needs an input file."
120
         exitWith $ ExitFailure 1
121

    
122
  let input_file = head args
123
  input_data <- readFile input_file
124

    
125
  request <- case (parseData input_data) of
126
               Bad err -> do
127
                 hPutStrLn stderr $ "Error: " ++ err
128
                 exitWith $ ExitFailure 1
129
               Ok rq -> return rq
130

    
131
  let Request _ _ _ csf = request
132
      sols = processRequest request >>= filterFails >>= processResults
133
  let (ok, info, rn) = case sols of
134
               Ok (info, sn) -> (True, "Request successful: " ++ info,
135
                                     map ((++ csf) . Node.name) sn)
136
               Bad s -> (False, "Request failed: " ++ s, [])
137
      resp = formatResponse ok info rn
138
  putStrLn resp