X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/fbb95f28346ff0d7eb0c1ac54b13a908209e07b7..33e44f0c0debb640d1d80c7d99d087afef8bef8a:/hail.hs diff --git a/hail.hs b/hail.hs index 74c2ac2..78eb8e1 100644 --- a/hail.hs +++ b/hail.hs @@ -4,7 +4,7 @@ {- -Copyright (C) 2009 Google Inc. +Copyright (C) 2009, 2010 Google Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,72 +26,98 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA module Main (main) where import Data.List -import Data.Function +import Data.Maybe (isJust, fromJust) import Monad -import System +import System (exitWith, ExitCode(..)) import System.IO import qualified System -import Text.Printf (printf) - import qualified Ganeti.HTools.Cluster as Cluster -import qualified Ganeti.HTools.Node as Node import Ganeti.HTools.CLI import Ganeti.HTools.IAlloc import Ganeti.HTools.Types -import Ganeti.HTools.Loader (RqType(..), Request(..)) +import Ganeti.HTools.Loader (RqType(..), Request(..), ClusterData(..)) +import Ganeti.HTools.ExtLoader (loadExternalData) -- | Options list and functions options :: [OptType] -options = [oShowVer, oShowHelp] - -processResults :: (Monad m) => Cluster.AllocSolution -> m (String, [Node.Node]) -processResults (fstats, successes, sols) = - case sols of - Nothing -> fail "No valid allocation solutions" - Just (best, (_, _, w)) -> - let tfails = length fstats - info = printf "successes %d, failures %d,\ - \ best score: %.8f for node(s) %s" - successes tfails - best (intercalate "/" . map Node.name $ w)::String - in return (info, w) +options = + [ oPrintNodes + , oDataFile + , oNodeSim + , oShowVer + , oShowHelp + ] + +processResults :: (Monad m) => + RqType -> Cluster.AllocSolution + -> m Cluster.AllocSolution +processResults _ (Cluster.AllocSolution { Cluster.asSolutions = [], + Cluster.asLog = msgs }) = + fail $ intercalate ", " msgs + +processResults (Evacuate _) as = return as + +processResults _ as = + case Cluster.asSolutions as of + _:[] -> return as + _ -> fail "Internal error: multiple allocation solutions" -- | Process a request and return new node lists processRequest :: Request -> Result Cluster.AllocSolution processRequest request = - let Request rqtype nl il _ = request + let Request rqtype (ClusterData gl nl il _) = request in case rqtype of - Allocate xi reqn -> Cluster.tryAlloc nl il xi reqn + Allocate xi reqn -> Cluster.tryMGAlloc gl nl il xi reqn Relocate idx reqn exnodes -> Cluster.tryReloc nl il idx reqn exnodes + Evacuate exnodes -> Cluster.tryEvac nl il exnodes + +-- | Reads the request from the data file(s) +readRequest :: Options -> [String] -> IO Request +readRequest opts args = do + when (null args) $ do + hPutStrLn stderr "Error: this program needs an input file." + exitWith $ ExitFailure 1 + + input_data <- readFile (head args) + r1 <- case (parseData input_data) of + Bad err -> do + hPutStrLn stderr $ "Error: " ++ err + exitWith $ ExitFailure 1 + Ok rq -> return rq + r2 <- if isJust (optDataFile opts) || (not . null . optNodeSim) opts + then do + cdata <- loadExternalData opts + let Request rqt _ = r1 + return $ Request rqt cdata + else return r1 + return r2 -- | Main function. main :: IO () main = do cmd_args <- System.getArgs - (_, args) <- parseOpts cmd_args "hail" options + (opts, args) <- parseOpts cmd_args "hail" options - when (null args) $ do - hPutStrLn stderr "Error: this program needs an input file." - exitWith $ ExitFailure 1 + let shownodes = optShowNodes opts + + request <- readRequest opts args - let input_file = head args - input_data <- readFile input_file + let Request rq cdata = request - request <- case (parseData input_data) of - Bad err -> do - hPutStrLn stderr $ "Error: " ++ err - exitWith $ ExitFailure 1 - Ok rq -> return rq + when (isJust shownodes) $ do + hPutStrLn stderr "Initial cluster status:" + hPutStrLn stderr $ Cluster.printNodes (cdNodes cdata) + (fromJust shownodes) - let Request _ _ _ csf = request - sols = processRequest request >>= processResults + let sols = processRequest request >>= processResults rq let (ok, info, rn) = case sols of - Ok (ginfo, sn) -> (True, "Request successful: " ++ ginfo, - map ((++ csf) . Node.name) sn) + Ok as -> (True, "Request successful: " ++ + intercalate ", " (Cluster.asLog as), + Cluster.asSolutions as) Bad s -> (False, "Request failed: " ++ s, []) - resp = formatResponse ok info rn + resp = formatResponse ok info rq rn putStrLn resp