1 {-| Solver for N+1 cluster errors
7 Copyright (C) 2009 Google Inc.
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.
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.
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
26 module Main (main) where
29 import Data.Maybe (isJust, fromJust)
31 import System (exitWith, ExitCode(..))
33 import qualified System
35 import Text.Printf (printf)
37 import qualified Ganeti.HTools.Cluster as Cluster
38 import qualified Ganeti.HTools.Node as Node
40 import Ganeti.HTools.CLI
41 import Ganeti.HTools.IAlloc
42 import Ganeti.HTools.Types
43 import Ganeti.HTools.Loader (RqType(..), Request(..))
45 -- | Options list and functions
47 options = [oPrintNodes, oShowVer, oShowHelp]
49 processResults :: (Monad m) =>
50 RqType -> Cluster.AllocSolution
51 -> m (String, Cluster.AllocSolution)
52 processResults _ (_, _, []) = fail "No valid allocation solutions"
53 processResults (Evacuate _) as@(fstats, successes, sols) =
54 let best = fst $ head sols
55 tfails = length fstats
56 info = printf "for last allocation, successes %d, failures %d,\
57 \ best score: %.8f" successes tfails best::String
60 processResults _ as@(fstats, successes, sols) =
62 (best, (_, _, w)):[] ->
63 let tfails = length fstats
64 info = printf "successes %d, failures %d,\
65 \ best score: %.8f for node(s) %s"
67 best (intercalate "/" . map Node.name $ w)::String
69 _ -> fail "Internal error: multiple allocation solutions"
71 -- | Process a request and return new node lists
72 processRequest :: Request
73 -> Result Cluster.AllocSolution
74 processRequest request =
75 let Request rqtype nl il _ = request
77 Allocate xi reqn -> Cluster.tryAlloc nl il xi reqn
78 Relocate idx reqn exnodes -> Cluster.tryReloc nl il idx reqn exnodes
79 Evacuate exnodes -> Cluster.tryEvac nl il exnodes
84 cmd_args <- System.getArgs
85 (opts, args) <- parseOpts cmd_args "hail" options
88 hPutStrLn stderr "Error: this program needs an input file."
89 exitWith $ ExitFailure 1
91 let input_file = head args
92 shownodes = optShowNodes opts
93 input_data <- readFile input_file
95 request <- case (parseData input_data) of
97 hPutStrLn stderr $ "Error: " ++ err
98 exitWith $ ExitFailure 1
101 let Request rq nl _ _ = request
103 when (isJust shownodes) $ do
104 hPutStrLn stderr "Initial cluster status:"
105 hPutStrLn stderr $ Cluster.printNodes nl (fromJust shownodes)
107 let sols = processRequest request >>= processResults rq
110 Ok (ginfo, (_, _, sn)) -> (True, "Request successful: " ++ ginfo,
112 Bad s -> (False, "Request failed: " ++ s, [])
113 resp = formatResponse ok info rq rn