, oOneline
, oNoHeaders
, oOutputDir
- , oNodeFile
- , oInstFile
+ , oDataFile
, oNodeSim
, oRapiMaster
, oLuxiSocket
, optOneline :: Bool -- ^ Switch output to a single line
, optOutPath :: FilePath -- ^ Path to the output directory
, optNoHeaders :: Bool -- ^ Do not show a header line
- , optNodeFile :: FilePath -- ^ Path to the nodes file
- , optNodeSet :: Bool -- ^ The nodes have been set by options
- , optInstFile :: FilePath -- ^ Path to the instances file
- , optInstSet :: Bool -- ^ The insts have been set by options
+ , optDataFile :: Maybe FilePath -- ^ Path to the cluster data file
, optNodeSim :: Maybe String -- ^ Cluster simulation mode
, optMaxLength :: Int -- ^ Stop after this many steps
, optMaster :: String -- ^ Collect data from RAPI
, optOneline = False
, optNoHeaders = False
, optOutPath = "."
- , optNodeFile = "nodes"
- , optNodeSet = False
- , optInstFile = "instances"
- , optInstSet = False
+ , optDataFile = Nothing
, optNodeSim = Nothing
, optMaxLength = -1
, optMaster = ""
(ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
"directory in which to write output files"
-oNodeFile :: OptType
-oNodeFile = Option "n" ["nodes"]
- (ReqArg (\ f o -> Ok o { optNodeFile = f,
- optNodeSet = True }) "FILE")
- "the node list FILE"
-
-oInstFile :: OptType
-oInstFile = Option "i" ["instances"]
- (ReqArg (\ f o -> Ok o { optInstFile = f,
- optInstSet = True }) "FILE")
- "the instance list FILE"
+oDataFile :: OptType
+oDataFile = Option "t" ["text-data"]
+ (ReqArg (\ f o -> Ok o { optDataFile = Just f }) "FILE")
+ "the cluster data FILE"
oNodeSim :: OptType
oNodeSim = Option "" ["simulate"]
import Data.Maybe (isJust, fromJust)
import Monad
-import System.Posix.Env
import System.IO
import System
import Text.Printf (printf, hPrintf)
import Ganeti.HTools.CLI
import Ganeti.HTools.Utils (sepSplit, tryRead)
--- | 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)
-
-- | Error beautifier
wrapIO :: IO (Result a) -> IO (Result a)
wrapIO = flip catch (return . Bad . show)
loadExternalData :: Options
-> IO (Node.List, Instance.List, [String], String)
loadExternalData opts = do
- (env_node, env_inst) <- parseEnv ()
- let nodef = if optNodeSet opts then optNodeFile opts
- else env_node
- instf = if optInstSet opts then optInstFile opts
- else env_inst
- mhost = optMaster opts
+ let mhost = optMaster opts
lsock = optLuxi opts
+ tfile = optDataFile opts
simdata = optNodeSim opts
setRapi = mhost /= ""
setLuxi = isJust lsock
setSim = isJust simdata
- setFiles = optNodeSet opts || optInstSet opts
- allSet = filter id [setRapi, setLuxi, setFiles]
+ setFile = isJust tfile
+ allSet = filter id [setRapi, setLuxi, setFile]
exTags = case optExTags opts of
Nothing -> []
Just etl -> map (++ ":") etl
#endif
| setLuxi -> wrapIO $ Luxi.loadData $ fromJust lsock
| setSim -> Simu.loadData $ fromJust simdata
- | otherwise -> wrapIO $ Text.loadData nodef instf
+ | setFile -> wrapIO $ Text.loadData $ fromJust tfile
+ | otherwise -> return $ Bad "No backend selected! Exiting."
let ldresult = input_data >>= Loader.mergeData util_data' exTags
(loaded_nl, il, tags, csf) <-
kerows <- mapM convert_fn rows
return $ assignIndices kerows
--- | Builds the cluster data from node\/instance files.
-loadData :: String -- ^ Node data in string format
- -> String -- ^ Instance data in string format
+-- | Builds the cluster data from text input.
+loadData :: String -- ^ Path to the text file
-> IO (Result (Node.AssocList, Instance.AssocList, [String]))
-loadData nfile ifile = do -- IO monad
- ndata <- readFile nfile
- idata <- readFile ifile
+loadData afile = do -- IO monad
+ fdata <- readFile afile
+ let flines = lines fdata
+ (nlines, ilines) = break null flines
return $ do
+ ifixed <- case ilines of
+ [] -> Bad "Invalid format of the input file (no instance data)"
+ _:xs -> Ok xs
{- node file: name t_mem n_mem f_mem t_disk f_disk -}
- (ktn, nl) <- loadTabular (lines ndata) loadNode
+ (ktn, nl) <- loadTabular nlines loadNode
{- instance file: name mem disk status pnode snode -}
- (_, il) <- loadTabular (lines idata) (loadInst ktn)
+ (_, il) <- loadTabular ifixed (loadInst ktn)
return (nl, il, [])
, oPrintInsts
, oPrintCommands
, oOneline
- , oNodeFile
- , oInstFile
+ , oDataFile
, oRapiMaster
, oLuxiSocket
, oExecJobs
options :: [OptType]
options =
[ oPrintNodes
- , oNodeFile
- , oInstFile
+ , oDataFile
, oNodeSim
, oRapiMaster
, oLuxiSocket