diff --git a/Ganeti/HTools/CLI.hs b/Ganeti/HTools/CLI.hs index 618eb1ef845bba6693d047bb1b780c97a7c61be9..c597bda8be41722aa5a5f63ffc296beb64820f41 100644 --- a/Ganeti/HTools/CLI.hs +++ b/Ganeti/HTools/CLI.hs @@ -8,9 +8,11 @@ and this is more IO oriented. module Ganeti.HTools.CLI ( CLIOptions(..) + , EToolOptions(..) , parseOpts , parseEnv , shTemplate + , loadExternalData ) where import System.Console.GetOpt @@ -23,12 +25,26 @@ import Text.Printf (printf) import qualified Data.Version import qualified Ganeti.HTools.Version as Version(version) +import qualified Ganeti.HTools.Rapi as Rapi +import qualified Ganeti.HTools.Text as Text +import qualified Ganeti.HTools.Loader as Loader + +import Ganeti.HTools.Types -- | Class for types which support show help and show version class CLIOptions a where showHelp :: a -> Bool showVersion :: a -> Bool +-- | Class for types which support the -i/-n/-m options +class EToolOptions a where + nodeFile :: a -> FilePath + nodeSet :: a -> Bool + instFile :: a -> FilePath + instSet :: a -> Bool + masterName :: a -> String + silent :: a -> Bool + -- | Command line parser, using the 'options' structure. parseOpts :: (CLIOptions b) => [String] -- ^ The command line arguments @@ -78,3 +94,34 @@ shTemplate = \ exit 0\n\ \ fi\n\ \}\n\n" + +-- | External tool data loader from a variety of sources +loadExternalData :: (EToolOptions a) => + a + -> IO (NodeList, InstanceList, String, NameList, NameList) +loadExternalData opts = do + (env_node, env_inst) <- parseEnv () + let nodef = if nodeSet opts then nodeFile opts + else env_node + instf = if instSet opts then instFile opts + else env_inst + input_data <- + case masterName opts of + "" -> Text.loadData nodef instf + host -> Rapi.loadData host + + let ldresult = input_data >>= Loader.mergeData + (loaded_nl, il, csf, ktn, kti) <- + (case ldresult of + Ok x -> return x + Bad s -> do + printf "Error: failed to load data. Details:\n%s\n" s + exitWith $ ExitFailure 1 + ) + let (fix_msgs, fixed_nl) = Loader.checkData loaded_nl il ktn kti + + unless (null fix_msgs || silent opts) $ do + putStrLn "Warning: cluster has inconsistent data:" + putStrLn . unlines . map (\s -> printf " - %s" s) $ fix_msgs + + return (fixed_nl, il, csf, ktn, kti) diff --git a/hbal.hs b/hbal.hs index 5db69d3ad08b0bc70989e64d073a2115abf897f9..6eda3476033e238d36e40c139bba564447497a23 100644 --- a/hbal.hs +++ b/hbal.hs @@ -19,9 +19,6 @@ import qualified Ganeti.HTools.Container as Container import qualified Ganeti.HTools.Cluster as Cluster import qualified Ganeti.HTools.Node as Node import qualified Ganeti.HTools.CLI as CLI -import qualified Ganeti.HTools.Rapi as Rapi -import qualified Ganeti.HTools.Text as Text -import qualified Ganeti.HTools.Loader as Loader import Ganeti.HTools.Utils import Ganeti.HTools.Types @@ -48,6 +45,14 @@ instance CLI.CLIOptions Options where showVersion = optShowVer showHelp = optShowHelp +instance CLI.EToolOptions Options where + nodeFile = optNodef + nodeSet = optNodeSet + instFile = optInstf + instSet = optInstSet + masterName = optMaster + silent a = (optVerbose a) == 0 + -- | Default values for the command line options. defaultOptions :: Options defaultOptions = Options @@ -175,32 +180,10 @@ main = do hPutStrLn stderr "Error: this program doesn't take any arguments." exitWith $ ExitFailure 1 - (env_node, env_inst) <- CLI.parseEnv () - let nodef = if optNodeSet opts then optNodef opts - else env_node - instf = if optInstSet opts then optInstf opts - else env_inst - oneline = optOneline opts + let oneline = optOneline opts verbose = optVerbose opts - input_data <- - case optMaster opts of - "" -> Text.loadData nodef instf - host -> Rapi.loadData host - - let ldresult = input_data >>= Loader.mergeData - - (loaded_nl, il, csf, ktn, kti) <- - (case ldresult of - Ok x -> return x - Bad s -> do - printf "Error: failed to load data. Details:\n%s\n" s - exitWith $ ExitFailure 1 - ) - let (fix_msgs, fixed_nl) = Loader.checkData loaded_nl il ktn kti - - unless (null fix_msgs || verbose == 0) $ do - putStrLn "Warning: cluster has inconsistent data:" - putStrLn . unlines . map (\s -> printf " - %s" s) $ fix_msgs + + (fixed_nl, il, csf, ktn, kti) <- CLI.loadExternalData opts let offline_names = optOffline opts all_names = snd . unzip $ ktn diff --git a/hn1.hs b/hn1.hs index 926833859e35f9bdf07175bebe4b1917adf61f03..e7fc122f11d371ae5de25bf5a2ebb94801c8c439 100644 --- a/hn1.hs +++ b/hn1.hs @@ -18,9 +18,6 @@ import qualified Ganeti.HTools.Container as Container import qualified Ganeti.HTools.Instance as Instance import qualified Ganeti.HTools.Cluster as Cluster import qualified Ganeti.HTools.CLI as CLI -import qualified Ganeti.HTools.Rapi as Rapi -import qualified Ganeti.HTools.Text as Text -import qualified Ganeti.HTools.Loader as Loader import Ganeti.HTools.Types -- | Command line options structure. @@ -44,6 +41,14 @@ instance CLI.CLIOptions Options where showVersion = optShowVer showHelp = optShowHelp +instance CLI.EToolOptions Options where + nodeFile = optNodef + nodeSet = optNodeSet + instFile = optInstf + instSet = optInstSet + masterName = optMaster + silent _ = False + -- | Default values for the command line options. defaultOptions :: Options defaultOptions = Options @@ -140,31 +145,7 @@ main = do hPutStrLn stderr "Error: this program doesn't take any arguments." exitWith $ ExitFailure 1 - (env_node, env_inst) <- CLI.parseEnv () - let nodef = if optNodeSet opts then optNodef opts - else env_node - instf = if optInstSet opts then optInstf opts - else env_inst - min_depth = optMinDepth opts - - input_data <- - case optMaster opts of - "" -> Text.loadData nodef instf - host -> Rapi.loadData host - let ldresult = input_data >>= Loader.mergeData - - (loaded_nl, il, csf, ktn, kti) <- - (case ldresult of - Ok x -> return x - Bad s -> do - printf "Error: failed to load data. Details:\n%s\n" s - exitWith $ ExitFailure 1 - ) - let (fix_msgs, nl) = Loader.checkData loaded_nl il ktn kti - - unless (null fix_msgs) $ do - putStrLn "Warning: cluster has inconsistent data:" - putStrLn . unlines . map (\s -> printf " - %s" s) $ fix_msgs + (nl, il, csf, ktn, kti) <- CLI.loadExternalData opts printf "Loaded %d nodes, %d instances\n" (Container.size nl) @@ -174,6 +155,8 @@ main = do printf "Note: Stripping common suffix of '%s' from names\n" csf let (bad_nodes, bad_instances) = Cluster.computeBadItems nl il + min_depth = optMinDepth opts + printf "Initial check done: %d bad nodes, %d bad instances.\n" (length bad_nodes) (length bad_instances)