{-
-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
, OptType
, parseOpts
, shTemplate
+ , defaultLuxiSocket
+ , maybePrintNodes
+ , maybePrintInsts
-- * The options
, oDataFile
, oDiskMoves
, oDynuFile
+ , oEvacMode
+ , oExInst
, oExTags
, oExecJobs
+ , oGroup
, oIDisk
, oIMem
, oINodes
, oMaxCpu
, oMaxSolLength
, oMinDisk
+ , oMinGain
+ , oMinGainLim
, oMinScore
, oNoHeaders
, oNodeSim
, oPrintNodes
, oQuiet
, oRapiMaster
+ , oSaveCluster
, oShowHelp
, oShowVer
, oTieredSpec
{ optDataFile :: Maybe FilePath -- ^ Path to the cluster data file
, optDiskMoves :: Bool -- ^ Allow disk moves
, optDynuFile :: Maybe FilePath -- ^ Optional file with dynamic use data
+ , optEvacMode :: Bool -- ^ Enable evacuation mode
+ , optExInst :: [String] -- ^ Instances to be excluded
, optExTags :: Maybe [String] -- ^ Tags to use for exclusion
, optExecJobs :: Bool -- ^ Execute the commands via Luxi
+ , optGroup :: Maybe GroupID -- ^ The UUID of the group to process
, optINodes :: Int -- ^ Nodes required for an instance
, optISpec :: RSpec -- ^ Requested instance specs
, optLuxi :: Maybe FilePath -- ^ Collect data from Luxi
, optMaxLength :: Int -- ^ Stop after this many steps
, optMcpu :: Double -- ^ Max cpu ratio for nodes
, optMdsk :: Double -- ^ Max disk usage ratio for nodes
+ , optMinGain :: Score -- ^ Min gain we aim for in a step
+ , optMinGainLim :: Score -- ^ Limit below which we apply mingain
, optMinScore :: Score -- ^ The minimum score we aim for
, optNoHeaders :: Bool -- ^ Do not show a header line
- , optNodeSim :: Maybe String -- ^ Cluster simulation mode
+ , optNodeSim :: [String] -- ^ Cluster simulation mode
, optOffline :: [String] -- ^ Names of offline nodes
, optOneline :: Bool -- ^ Switch output to a single line
, optOutPath :: FilePath -- ^ Path to the output directory
+ , optSaveCluster :: Maybe FilePath -- ^ Save cluster state to this file
, optShowCmds :: Maybe FilePath -- ^ Whether to show the command list
, optShowHelp :: Bool -- ^ Just show the help
, optShowInsts :: Bool -- ^ Whether to show the instance map
{ optDataFile = Nothing
, optDiskMoves = True
, optDynuFile = Nothing
+ , optEvacMode = False
+ , optExInst = []
, optExTags = Nothing
, optExecJobs = False
+ , optGroup = Nothing
, optINodes = 2
, optISpec = RSpec 1 4096 102400
, optLuxi = Nothing
, optMaster = ""
, optMaxLength = -1
- , optMcpu = -1
- , optMdsk = -1
+ , optMcpu = defVcpuRatio
+ , optMdsk = defReservedDiskRatio
+ , optMinGain = 1e-2
+ , optMinGainLim = 1e-1
, optMinScore = 1e-9
, optNoHeaders = False
- , optNodeSim = Nothing
+ , optNodeSim = []
, optOffline = []
, optOneline = False
, optOutPath = "."
+ , optSaveCluster = Nothing
, optShowCmds = Nothing
, optShowHelp = False
, optShowInsts = False
(ReqArg (\ f opts -> Ok opts { optDynuFile = Just f }) "FILE")
"Import dynamic utilisation data from the given FILE"
+oEvacMode :: OptType
+oEvacMode = Option "E" ["evac-mode"]
+ (NoArg (\opts -> Ok opts { optEvacMode = True }))
+ "enable evacuation mode, where the algorithm only moves \
+ \ instances away from offline and drained nodes"
+
+oExInst :: OptType
+oExInst = Option "" ["exclude-instances"]
+ (ReqArg (\ f opts -> Ok opts { optExInst = sepSplit ',' f }) "INSTS")
+ "exclude given instances from any moves"
+
oExTags :: OptType
oExTags = Option "" ["exclusion-tags"]
(ReqArg (\ f opts -> Ok opts { optExTags = Just $ sepSplit ',' f })
"execute the suggested moves via Luxi (only available when using\
\ it for data gathering)"
+oGroup :: OptType
+oGroup = Option "G" ["group"]
+ (ReqArg (\ f o -> Ok o { optGroup = Just f }) "ID")
+ "the ID of the group to balance"
+
oIDisk :: OptType
oIDisk = Option "" ["disk"]
(ReqArg (\ d opts ->
oMaxCpu :: OptType
oMaxCpu = Option "" ["max-cpu"]
(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 (from 1\
+ \ upwards) [64]"
oMaxSolLength :: OptType
oMaxSolLength = Option "l" ["max-length"]
oMinDisk :: OptType
oMinDisk = Option "" ["min-disk"]
(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) [0]"
+
+oMinGain :: OptType
+oMinGain = Option "g" ["min-gain"]
+ (ReqArg (\ g opts -> Ok opts { optMinGain = read g }) "DELTA")
+ "minimum gain to aim for in a balancing step before giving up"
+
+oMinGainLim :: OptType
+oMinGainLim = Option "" ["min-gain-limit"]
+ (ReqArg (\ g opts -> Ok opts { optMinGainLim = read g }) "SCORE")
+ "minimum cluster score for which we start checking the min-gain"
oMinScore :: OptType
oMinScore = Option "e" ["min-score"]
(ReqArg (\ e opts -> Ok opts { optMinScore = read e }) "EPSILON")
- " mininum score to aim for"
+ "mininum score to aim for"
oNoHeaders :: OptType
oNoHeaders = Option "" ["no-headers"]
oNodeSim :: OptType
oNodeSim = Option "" ["simulate"]
- (ReqArg (\ f o -> Ok o { optNodeSim = Just f }) "SPEC")
+ (ReqArg (\ f o -> Ok o { optNodeSim = f:optNodeSim o }) "SPEC")
"simulate an empty cluster, given as 'num_nodes,disk,ram,cpu'"
oOfflineNode :: OptType
oPrintNodes :: OptType
oPrintNodes = Option "p" ["print-nodes"]
(OptArg ((\ f opts ->
- let splitted = sepSplit ',' f
+ let (prefix, realf) = case f of
+ '+':rest -> (["+"], rest)
+ _ -> ([], f)
+ splitted = prefix ++ sepSplit ',' realf
in Ok opts { optShowNodes = Just splitted }) .
fromMaybe []) "FIELDS")
"print the final node list"
(ReqArg (\ m opts -> Ok opts { optMaster = m }) "ADDRESS")
"collect data via RAPI at the given ADDRESS"
+oSaveCluster :: OptType
+oSaveCluster = Option "S" ["save"]
+ (ReqArg (\ f opts -> Ok opts { optSaveCluster = Just f }) "FILE")
+ "Save cluster state at the end of the processing to FILE"
+
oShowHelp :: OptType
oShowHelp = Option "h" ["help"]
(NoArg (\ opts -> Ok opts { optShowHelp = True}))
tspec <-
case prs of
[dsk, ram, cpu] -> return $ RSpec cpu ram dsk
- _ -> Bad $ "Invalid specification: " ++ inp
+ _ -> Bad $ "Invalid specification: " ++ inp ++
+ ", expected disk,ram,cpu"
return $ opts { optTieredSpec = Just tspec } )
"TSPEC")
"enable tiered specs allocation, given as 'disk,ram,cpu'"
printf "%s %s\ncompiled with %s %s\nrunning on %s %s\n"
progname Version.version
compilerName (Data.Version.showVersion compilerVersion)
- os arch
+ os arch :: IO ()
exitWith ExitSuccess
return (po, args)
(_, _, errs) -> do
\ exit 0\n\
\ fi\n\
\}\n\n"
+
+-- | Optionally print the node list.
+maybePrintNodes :: Maybe [String] -- ^ The field list
+ -> String -- ^ Informational message
+ -> ([String] -> String) -- ^ Function to generate the listing
+ -> IO ()
+maybePrintNodes Nothing _ _ = return ()
+maybePrintNodes (Just fields) msg fn = do
+ hPutStrLn stderr ""
+ hPutStrLn stderr (msg ++ " status:")
+ hPutStrLn stderr $ fn fields
+
+
+-- | Optionally print the instance list.
+maybePrintInsts :: Bool -- ^ Whether to print the instance list
+ -> String -- ^ Type of the instance map (e.g. initial)
+ -> String -- ^ The instance data
+ -> IO ()
+maybePrintInsts do_print msg instdata =
+ when do_print $ do
+ hPutStrLn stderr ""
+ hPutStrLn stderr $ msg ++ " instance map:"
+ hPutStr stderr instdata