module Ganeti.HTools.CLI
( CLIOptions(..)
+ , EToolOptions(..)
, parseOpts
, parseEnv
, shTemplate
+ , loadExternalData
) where
import System.Console.GetOpt
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 qualified Ganeti.HTools.Instance as Instance
+import qualified Ganeti.HTools.Node as Node
--- | Class for types which support show help and show version
+import Ganeti.HTools.Types
+
+-- | Class for types which support show help and show version.
class CLIOptions a where
+ -- | Denotes whether the show help option has been passed.
showHelp :: a -> Bool
+ -- | Denotes whether the show version option has been passed.
showVersion :: a -> Bool
+-- | Class for types which support the -i\/-n\/-m options.
+class EToolOptions a where
+ -- | Returns the node file name.
+ nodeFile :: a -> FilePath
+ -- | Tells whether the node file has been passed as an option.
+ nodeSet :: a -> Bool
+ -- | Returns the instance file name.
+ instFile :: a -> FilePath
+ -- | Tells whether the instance file has been passed as an option.
+ instSet :: a -> Bool
+ -- | Rapi target, if one has been passed.
+ masterName :: a -> String
+ -- | Whether to be less verbose.
+ silent :: a -> Bool
+
-- | Command line parser, using the 'options' structure.
parseOpts :: (CLIOptions b) =>
[String] -- ^ The command line arguments
where header = printf "%s %s\nUsage: %s [OPTION...]"
progname Version.version progname
--- | Parse the environment and return the node/instance names.
--- This also hardcodes here the default node/instance file names.
+-- | Parse the environment and return the node\/instance names.
+--
+-- This also hardcodes here the default node\/instance file names.
parseEnv :: () -> IO (String, String)
parseEnv () = do
a <- getEnvDefault "HTOOLS_NODES" "nodes"
b <- getEnvDefault "HTOOLS_INSTANCES" "instances"
return (a, b)
--- | A shell script template for autogenerated scripts
+-- | A shell script template for autogenerated scripts.
shTemplate :: String
shTemplate =
printf "#!/bin/sh\n\n\
\ exit 0\n\
\ fi\n\
\}\n\n"
+
+-- | External tool data loader from a variety of sources.
+loadExternalData :: (EToolOptions a) =>
+ a
+ -> IO (Node.List, Instance.List, String)
+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) <-
+ (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
+
+ 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)