Statistics
| Branch: | Tag: | Revision:

root / hail.hs @ e2fa2baf

History | View | Annotate | Download (4.2 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 Data.Maybe (isJust, fromJust)
31
import Monad
32
import System
33
import System.IO
34
import System.Console.GetOpt
35
import qualified System
36

    
37
import Text.Printf (printf)
38

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

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

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

    
61
instance CLI.CLIOptions Options where
62
    showVersion = optShowVer
63
    showHelp    = optShowHelp
64

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

    
76

    
77
filterFails :: (Monad m) => [(Maybe Node.List, [Node.Node])]
78
            -> m [(Node.List, [Node.Node])]
79
filterFails sols =
80
    if null sols then fail "No nodes onto which to allocate at all"
81
    else let sols' = filter (isJust . fst) sols
82
         in if null sols' then
83
                fail "No valid allocation solutions"
84
            else
85
                return $ map (\(x, y) -> (fromJust x, y)) sols'
86

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

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

    
106
  when (null args) $ do
107
         hPutStrLn stderr "Error: this program needs an input file."
108
         exitWith $ ExitFailure 1
109

    
110
  let input_file = head args
111
  input_data <- readFile input_file
112

    
113
  request <- case (parseData input_data) of
114
               Bad err -> do
115
                 putStrLn $ "Error: " ++ err
116
                 exitWith $ ExitFailure 1
117
               Ok rq -> return rq
118

    
119
  let Request rqtype nl il csf = request
120
      new_nodes = case rqtype of
121
                    Allocate xi reqn -> Cluster.tryAlloc nl il xi reqn
122
                    Relocate idx reqn exnodes ->
123
                        Cluster.tryReloc nl il idx reqn exnodes
124
  let sols = new_nodes >>= filterFails >>= processResults
125
  let (ok, info, rn) = case sols of
126
               Ok (info, sn) -> (True, "Request successful: " ++ info,
127
                                     map ((++ csf) . Node.name) sn)
128
               Bad s -> (False, "Request failed: " ++ s, [])
129
      resp = formatResponse ok info rn
130
  putStrLn resp