- [ Option ['p'] ["print-nodes"]
- (NoArg (\ opts -> opts { optShowNodes = True }))
- "print the final node list"
- , Option ['n'] ["nodes"]
- (ReqArg (\ f opts -> opts { optNodef = f, optNodeSet = True }) "FILE")
- "the node list FILE"
- , Option ['i'] ["instances"]
- (ReqArg (\ f opts -> opts { optInstf = f, optInstSet = True }) "FILE")
- "the instance list FILE"
- , Option ['m'] ["master"]
- (ReqArg (\ m opts -> opts { optMaster = m }) "ADDRESS")
- "collect data via RAPI at the given ADDRESS"
- , Option ['v'] ["verbose"]
- (NoArg (\ opts -> opts { optVerbose = (optVerbose opts) + 1 }))
- "increase the verbosity level"
- , Option ['q'] ["quiet"]
- (NoArg (\ opts -> opts { optVerbose = (optVerbose opts) - 1 }))
- "decrease the verbosity level"
- , Option ['O'] ["offline"]
- (ReqArg (\ n opts -> opts { optOffline = n:optOffline opts }) "NODE")
- "set node as offline"
- , Option [] ["memory"]
- (ReqArg (\ m opts -> opts { optIMem = read m }) "MEMORY")
- "memory size for instances"
- , Option [] ["disk"]
- (ReqArg (\ d opts -> opts { optIDsk = read d }) "DISK")
- "disk size for instances"
- , Option [] ["vcpus"]
- (ReqArg (\ p opts -> opts { optIVCPUs = read p }) "NUM")
- "number of virtual cpus for instances"
- , Option [] ["req-nodes"]
- (ReqArg (\ n opts -> opts { optINodes = read n }) "NODES")
- "number of nodes for the new instances (1=plain, 2=mirrored)"
- , Option [] ["max-cpu"]
- (ReqArg (\ n opts -> opts { optMcpu = read n }) "RATIO")
- "maximum virtual-to-physical cpu ratio for nodes"
- , Option [] ["min-disk"]
- (ReqArg (\ n opts -> opts { optMdsk = read n }) "RATIO")
- "minimum free disk space for nodes (between 0 and 1)"
- , Option ['V'] ["version"]
- (NoArg (\ opts -> opts { optShowVer = True}))
- "show the version of the program"
- , Option ['h'] ["help"]
- (NoArg (\ opts -> opts { optShowHelp = True}))
- "show help"
+ [ oPrintNodes
+ , oDataFile
+ , oNodeSim
+ , oRapiMaster
+ , oLuxiSocket
+ , oVerbose
+ , oQuiet
+ , oOfflineNode
+ , oIMem
+ , oIDisk
+ , oIVcpus
+ , oINodes
+ , oMaxCpu
+ , oMinDisk
+ , oTieredSpec
+ , oSaveCluster
+ , oShowVer
+ , oShowHelp
+ ]
+
+-- | The allocation phase we're in (initial, after tiered allocs, or
+-- after regular allocation).
+data Phase = PInitial
+ | PFinal
+ | PTiered
+
+statsData :: [(String, Cluster.CStats -> String)]
+statsData = [ ("SCORE", printf "%.8f" . Cluster.csScore)
+ , ("INST_CNT", printf "%d" . Cluster.csNinst)
+ , ("MEM_FREE", printf "%d" . Cluster.csFmem)
+ , ("MEM_AVAIL", printf "%d" . Cluster.csAmem)
+ , ("MEM_RESVD",
+ \cs -> printf "%d" (Cluster.csFmem cs - Cluster.csAmem cs))
+ , ("MEM_INST", printf "%d" . Cluster.csImem)
+ , ("MEM_OVERHEAD",
+ \cs -> printf "%d" (Cluster.csXmem cs + Cluster.csNmem cs))
+ , ("MEM_EFF",
+ \cs -> printf "%.8f" (fromIntegral (Cluster.csImem cs) /
+ Cluster.csTmem cs))
+ , ("DSK_FREE", printf "%d" . Cluster.csFdsk)
+ , ("DSK_AVAIL", printf "%d". Cluster.csAdsk)
+ , ("DSK_RESVD",
+ \cs -> printf "%d" (Cluster.csFdsk cs - Cluster.csAdsk cs))
+ , ("DSK_INST", printf "%d" . Cluster.csIdsk)
+ , ("DSK_EFF",
+ \cs -> printf "%.8f" (fromIntegral (Cluster.csIdsk cs) /
+ Cluster.csTdsk cs))
+ , ("CPU_INST", printf "%d" . Cluster.csIcpu)
+ , ("CPU_EFF",
+ \cs -> printf "%.8f" (fromIntegral (Cluster.csIcpu cs) /
+ Cluster.csTcpu cs))
+ , ("MNODE_MEM_AVAIL", printf "%d" . Cluster.csMmem)
+ , ("MNODE_DSK_AVAIL", printf "%d" . Cluster.csMdsk)
+ ]
+
+specData :: [(String, RSpec -> String)]
+specData = [ ("MEM", printf "%d" . rspecMem)
+ , ("DSK", printf "%d" . rspecDsk)
+ , ("CPU", printf "%d" . rspecCpu)
+ ]
+
+clusterData :: [(String, Cluster.CStats -> String)]
+clusterData = [ ("MEM", printf "%.0f" . Cluster.csTmem)
+ , ("DSK", printf "%.0f" . Cluster.csTdsk)
+ , ("CPU", printf "%.0f" . Cluster.csTcpu)
+ , ("VCPU", printf "%d" . Cluster.csVcpu)
+ ]
+
+-- | Function to print stats for a given phase
+printStats :: Phase -> Cluster.CStats -> [(String, String)]
+printStats ph cs =
+ map (\(s, fn) -> (printf "%s_%s" kind s, fn cs)) statsData
+ where kind = case ph of
+ PInitial -> "INI"
+ PFinal -> "FIN"
+ PTiered -> "TRL"
+
+-- | Print final stats and related metrics
+printResults :: Node.List -> Int -> Int -> [(FailMode, Int)] -> IO ()
+printResults fin_nl num_instances allocs sreason = do
+ let fin_stats = Cluster.totalResources fin_nl
+ fin_instances = num_instances + allocs
+
+ when (num_instances + allocs /= Cluster.csNinst fin_stats) $
+ do
+ hPrintf stderr "ERROR: internal inconsistency, allocated (%d)\
+ \ != counted (%d)\n" (num_instances + allocs)
+ (Cluster.csNinst fin_stats) :: IO ()
+ exitWith $ ExitFailure 1
+
+ printKeys $ printStats PFinal fin_stats
+ printKeys [ ("ALLOC_USAGE", printf "%.8f"
+ ((fromIntegral num_instances::Double) /
+ fromIntegral fin_instances))
+ , ("ALLOC_INSTANCES", printf "%d" allocs)
+ , ("ALLOC_FAIL_REASON", map toUpper . show . fst $ head sreason)
+ ]
+ printKeys $ map (\(x, y) -> (printf "ALLOC_%s_CNT" (show x),
+ printf "%d" y)) sreason
+ -- this should be the final entry
+ printKeys [("OK", "1")]
+
+formatRSpec :: Double -> String -> RSpec -> [(String, String)]
+formatRSpec m_cpu s r =
+ [ ("KM_" ++ s ++ "_CPU", show $ rspecCpu r)
+ , ("KM_" ++ s ++ "_NPU", show $ fromIntegral (rspecCpu r) / m_cpu)
+ , ("KM_" ++ s ++ "_MEM", show $ rspecMem r)
+ , ("KM_" ++ s ++ "_DSK", show $ rspecDsk r)