Skip to content
Snippets Groups Projects
Commit 2f567ac0 authored by Iustin Pop's avatar Iustin Pop
Browse files

Convert option parsing to a monadic flow

This allows us to do verification of option arguments in the assignment
functions themselves.
parent ce0392e6
No related branches found
No related tags found
No related merge requests found
...@@ -144,21 +144,21 @@ defaultOptions = Options ...@@ -144,21 +144,21 @@ defaultOptions = Options
} }
-- | Abrreviation for the option type -- | Abrreviation for the option type
type OptType = OptDescr (Options -> Options) type OptType = OptDescr (Options -> Result Options)
oPrintNodes :: OptType oPrintNodes :: OptType
oPrintNodes = Option "p" ["print-nodes"] oPrintNodes = Option "p" ["print-nodes"]
(NoArg (\ opts -> opts { optShowNodes = True })) (NoArg (\ opts -> Ok opts { optShowNodes = True }))
"print the final node list" "print the final node list"
oPrintInsts :: OptType oPrintInsts :: OptType
oPrintInsts = Option "" ["print-instances"] oPrintInsts = Option "" ["print-instances"]
(NoArg (\ opts -> opts { optShowInsts = True })) (NoArg (\ opts -> Ok opts { optShowInsts = True }))
"print the final instance map" "print the final instance map"
oPrintCommands :: OptType oPrintCommands :: OptType
oPrintCommands = Option "C" ["print-commands"] oPrintCommands = Option "C" ["print-commands"]
(OptArg ((\ f opts -> opts { optShowCmds = Just f }) . (OptArg ((\ f opts -> Ok opts { optShowCmds = Just f }) .
fromMaybe "-") fromMaybe "-")
"FILE") "FILE")
"print the ganeti command list for reaching the solution,\ "print the ganeti command list for reaching the solution,\
...@@ -167,126 +167,128 @@ oPrintCommands = Option "C" ["print-commands"] ...@@ -167,126 +167,128 @@ oPrintCommands = Option "C" ["print-commands"]
oOneline :: OptType oOneline :: OptType
oOneline = Option "o" ["oneline"] oOneline = Option "o" ["oneline"]
(NoArg (\ opts -> opts { optOneline = True })) (NoArg (\ opts -> Ok opts { optOneline = True }))
"print the ganeti command list for reaching the solution" "print the ganeti command list for reaching the solution"
oNoHeaders :: OptType oNoHeaders :: OptType
oNoHeaders = Option "" ["no-headers"] oNoHeaders = Option "" ["no-headers"]
(NoArg (\ opts -> opts { optNoHeaders = True })) (NoArg (\ opts -> Ok opts { optNoHeaders = True }))
"do not show a header line" "do not show a header line"
oOutputDir :: OptType oOutputDir :: OptType
oOutputDir = Option "d" ["output-dir"] oOutputDir = Option "d" ["output-dir"]
(ReqArg (\ d opts -> opts { optOutPath = d }) "PATH") (ReqArg (\ d opts -> Ok opts { optOutPath = d }) "PATH")
"directory in which to write output files" "directory in which to write output files"
oNodeFile :: OptType oNodeFile :: OptType
oNodeFile = Option "n" ["nodes"] oNodeFile = Option "n" ["nodes"]
(ReqArg (\ f o -> o { optNodeFile = f, optNodeSet = True }) "FILE") (ReqArg (\ f o -> Ok o { optNodeFile = f,
optNodeSet = True }) "FILE")
"the node list FILE" "the node list FILE"
oInstFile :: OptType oInstFile :: OptType
oInstFile = Option "i" ["instances"] oInstFile = Option "i" ["instances"]
(ReqArg (\ f o -> o { optInstFile = f, optInstSet = True }) "FILE") (ReqArg (\ f o -> Ok o { optInstFile = f,
optInstSet = True }) "FILE")
"the instance list FILE" "the instance list FILE"
oNodeSim :: OptType oNodeSim :: OptType
oNodeSim = Option "" ["simulate"] oNodeSim = Option "" ["simulate"]
(ReqArg (\ f o -> o { optNodeSim = Just f }) "SPEC") (ReqArg (\ f o -> Ok o { optNodeSim = Just f }) "SPEC")
"simulate an empty cluster, given as 'num_nodes,disk,memory,cpus'" "simulate an empty cluster, given as 'num_nodes,disk,memory,cpus'"
oRapiMaster :: OptType oRapiMaster :: OptType
oRapiMaster = Option "m" ["master"] oRapiMaster = Option "m" ["master"]
(ReqArg (\ m opts -> opts { optMaster = m }) "ADDRESS") (ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
"collect data via RAPI at the given ADDRESS" "collect data via RAPI at the given ADDRESS"
oLuxiSocket :: OptType oLuxiSocket :: OptType
oLuxiSocket = Option "L" ["luxi"] oLuxiSocket = Option "L" ["luxi"]
(OptArg ((\ f opts -> opts { optLuxi = Just f }) . (OptArg ((\ f opts -> Ok opts { optLuxi = Just f }) .
fromMaybe defaultLuxiSocket) "SOCKET") fromMaybe defaultLuxiSocket) "SOCKET")
"collect data via Luxi, optionally using the given SOCKET path" "collect data via Luxi, optionally using the given SOCKET path"
oExecJobs :: OptType oExecJobs :: OptType
oExecJobs = Option "X" ["exec"] oExecJobs = Option "X" ["exec"]
(NoArg (\ opts -> opts { optExecJobs = True})) (NoArg (\ opts -> Ok opts { optExecJobs = True}))
"execute the suggested moves via Luxi (only available when using\ "execute the suggested moves via Luxi (only available when using\
\ it for data gathering" \ it for data gathering"
oVerbose :: OptType oVerbose :: OptType
oVerbose = Option "v" ["verbose"] oVerbose = Option "v" ["verbose"]
(NoArg (\ opts -> opts { optVerbose = optVerbose opts + 1 })) (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts + 1 }))
"increase the verbosity level" "increase the verbosity level"
oQuiet :: OptType oQuiet :: OptType
oQuiet = Option "q" ["quiet"] oQuiet = Option "q" ["quiet"]
(NoArg (\ opts -> opts { optVerbose = optVerbose opts - 1 })) (NoArg (\ opts -> Ok opts { optVerbose = optVerbose opts - 1 }))
"decrease the verbosity level" "decrease the verbosity level"
oOfflineNode :: OptType oOfflineNode :: OptType
oOfflineNode = Option "O" ["offline"] oOfflineNode = Option "O" ["offline"]
(ReqArg (\ n o -> o { optOffline = n:optOffline o }) "NODE") (ReqArg (\ n o -> Ok o { optOffline = n:optOffline o }) "NODE")
"set node as offline" "set node as offline"
oMaxSolLength :: OptType oMaxSolLength :: OptType
oMaxSolLength = Option "l" ["max-length"] oMaxSolLength = Option "l" ["max-length"]
(ReqArg (\ i opts -> opts { optMaxLength = read i::Int }) "N") (ReqArg (\ i opts -> Ok opts { optMaxLength = read i }) "N")
"cap the solution at this many moves (useful for very\ "cap the solution at this many moves (useful for very\
\ unbalanced clusters)" \ unbalanced clusters)"
oMinScore :: OptType oMinScore :: OptType
oMinScore = Option "e" ["min-score"] oMinScore = Option "e" ["min-score"]
(ReqArg (\ e opts -> opts { optMinScore = read e }) "EPSILON") (ReqArg (\ e opts -> Ok opts { optMinScore = read e }) "EPSILON")
" mininum score to aim for" " mininum score to aim for"
oIMem :: OptType oIMem :: OptType
oIMem = Option "" ["memory"] oIMem = Option "" ["memory"]
(ReqArg (\ m opts -> opts { optIMem = read m }) "MEMORY") (ReqArg (\ m opts -> Ok opts { optIMem = read m }) "MEMORY")
"memory size for instances" "memory size for instances"
oIDisk :: OptType oIDisk :: OptType
oIDisk = Option "" ["disk"] oIDisk = Option "" ["disk"]
(ReqArg (\ d opts -> opts { optIDsk = read d }) "DISK") (ReqArg (\ d opts -> Ok opts { optIDsk = read d }) "DISK")
"disk size for instances" "disk size for instances"
oIVcpus :: OptType oIVcpus :: OptType
oIVcpus = Option "" ["vcpus"] oIVcpus = Option "" ["vcpus"]
(ReqArg (\ p opts -> opts { optIVCPUs = read p }) "NUM") (ReqArg (\ p opts -> Ok opts { optIVCPUs = read p }) "NUM")
"number of virtual cpus for instances" "number of virtual cpus for instances"
oINodes :: OptType oINodes :: OptType
oINodes = Option "" ["req-nodes"] oINodes = Option "" ["req-nodes"]
(ReqArg (\ n opts -> opts { optINodes = read n }) "NODES") (ReqArg (\ n opts -> Ok opts { optINodes = read n }) "NODES")
"number of nodes for the new instances (1=plain, 2=mirrored)" "number of nodes for the new instances (1=plain, 2=mirrored)"
oMaxCpu :: OptType oMaxCpu :: OptType
oMaxCpu = Option "" ["max-cpu"] oMaxCpu = Option "" ["max-cpu"]
(ReqArg (\ n opts -> opts { optMcpu = read n }) "RATIO") (ReqArg (\ n opts -> Ok opts { optMcpu = read n }) "RATIO")
"maximum virtual-to-physical cpu ratio for nodes" "maximum virtual-to-physical cpu ratio for nodes"
oMinDisk :: OptType oMinDisk :: OptType
oMinDisk = Option "" ["min-disk"] oMinDisk = Option "" ["min-disk"]
(ReqArg (\ n opts -> opts { optMdsk = read n }) "RATIO") (ReqArg (\ n opts -> Ok opts { optMdsk = read n }) "RATIO")
"minimum free disk space for nodes (between 0 and 1)" "minimum free disk space for nodes (between 0 and 1)"
oDiskMoves :: OptType oDiskMoves :: OptType
oDiskMoves = Option "" ["no-disk-moves"] oDiskMoves = Option "" ["no-disk-moves"]
(NoArg (\ opts -> opts { optDiskMoves = False})) (NoArg (\ opts -> Ok opts { optDiskMoves = False}))
"disallow disk moves from the list of allowed instance changes,\ "disallow disk moves from the list of allowed instance changes,\
\ thus allowing only the 'cheap' failover/migrate operations" \ thus allowing only the 'cheap' failover/migrate operations"
oDynuFile :: OptType oDynuFile :: OptType
oDynuFile = Option "U" ["dynu-file"] oDynuFile = Option "U" ["dynu-file"]
(ReqArg (\ f opts -> opts { optDynuFile = Just f }) "FILE") (ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
"Import dynamic utilisation data from the given FILE" "Import dynamic utilisation data from the given FILE"
oShowVer :: OptType oShowVer :: OptType
oShowVer = Option "V" ["version"] oShowVer = Option "V" ["version"]
(NoArg (\ opts -> opts { optShowVer = True})) (NoArg (\ opts -> Ok opts { optShowVer = True}))
"show the version of the program" "show the version of the program"
oShowHelp :: OptType oShowHelp :: OptType
oShowHelp = Option "h" ["help"] oShowHelp = Option "h" ["help"]
(NoArg (\ opts -> opts { optShowHelp = True})) (NoArg (\ opts -> Ok opts { optShowHelp = True}))
"show help" "show help"
-- | Usage info -- | Usage info
...@@ -305,7 +307,14 @@ parseOpts argv progname options = ...@@ -305,7 +307,14 @@ parseOpts argv progname options =
case getOpt Permute options argv of case getOpt Permute options argv of
(o, n, []) -> (o, n, []) ->
do do
let resu@(po, _) = (foldl (flip id) defaultOptions o, n) let (pr, args) = (foldM (flip id) defaultOptions o, n)
po <- (case pr of
Bad msg -> do
hPutStrLn stderr "Error while parsing command\
\line arguments:"
hPutStrLn stderr msg
exitWith $ ExitFailure 1
Ok val -> return val)
when (optShowHelp po) $ do when (optShowHelp po) $ do
putStr $ usageHelp progname options putStr $ usageHelp progname options
exitWith ExitSuccess exitWith ExitSuccess
...@@ -315,7 +324,7 @@ parseOpts argv progname options = ...@@ -315,7 +324,7 @@ parseOpts argv progname options =
compilerName (Data.Version.showVersion compilerVersion) compilerName (Data.Version.showVersion compilerVersion)
os arch os arch
exitWith ExitSuccess exitWith ExitSuccess
return resu return (po, args)
(_, _, errs) -> do (_, _, errs) -> do
hPutStrLn stderr $ "Command line error: " ++ concat errs hPutStrLn stderr $ "Command line error: " ++ concat errs
hPutStrLn stderr $ usageHelp progname options hPutStrLn stderr $ usageHelp progname options
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment