diff --git a/Ganeti/HTools/CLI.hs b/Ganeti/HTools/CLI.hs index 4ef7a9f9e2f4cce6adf24a9dbdcae4ece2bd893d..9462f782313abd56077f989bbf79501ab432f539 100644 --- a/Ganeti/HTools/CLI.hs +++ b/Ganeti/HTools/CLI.hs @@ -34,6 +34,7 @@ module Ganeti.HTools.CLI , shTemplate -- * The options , oPrintNodes + , oPrintInsts , oPrintCommands , oOneline , oNoHeaders @@ -79,6 +80,7 @@ defaultLuxiSocket = "/var/run/ganeti/socket/ganeti-master" -- | Command line options structure. data Options = Options { optShowNodes :: Bool -- ^ Whether to show node status + , optShowInsts :: Bool -- ^ Whether to show the instance map , optShowCmds :: Maybe FilePath -- ^ Whether to show the command list , optOneline :: Bool -- ^ Switch output to a single line , optOutPath :: FilePath -- ^ Path to the output directory @@ -110,6 +112,7 @@ data Options = Options defaultOptions :: Options defaultOptions = Options { optShowNodes = False + , optShowInsts = False , optShowCmds = Nothing , optOneline = False , optNoHeaders = False @@ -145,6 +148,11 @@ oPrintNodes = Option "p" ["print-nodes"] (NoArg (\ opts -> opts { optShowNodes = True })) "print the final node list" +oPrintInsts :: OptType +oPrintInsts = Option "" ["print-instances"] + (NoArg (\ opts -> opts { optShowInsts = True })) + "print the final instance map" + oPrintCommands :: OptType oPrintCommands = Option "C" ["print-commands"] (OptArg ((\ f opts -> opts { optShowCmds = Just f }) . diff --git a/Ganeti/HTools/Cluster.hs b/Ganeti/HTools/Cluster.hs index ccc516a8c3dd0201945ccaddea470aa19f82bc6d..5d9656c99bed0f8798b974a319ec9d35ae2663ff 100644 --- a/Ganeti/HTools/Cluster.hs +++ b/Ganeti/HTools/Cluster.hs @@ -41,9 +41,11 @@ module Ganeti.HTools.Cluster , printSolution , printSolutionLine , formatCmds - , printNodes , involvedNodes , splitJobs + -- * Display functions + , printNodes + , printInsts -- * Balacing functions , checkMove , tryBalance @@ -684,6 +686,20 @@ printNodes nl = "pri" "sec" "p_fmem" "p_fdsk" "r_cpu"::String in unlines (header:map helper snl) +-- | Print the instance list. +printInsts :: Node.List -> Instance.List -> String +printInsts nl il = + let sil = sortBy (compare `on` Instance.idx) (Container.elems il) + m_name = maximum . map (length . Instance.name) $ sil + m_nnm = maximum . map (length . Node.name) $ Container.elems nl + helper inst = printf "%2s %-*s %-*s %-*s" + " " m_name (Instance.name inst) + m_nnm (Container.nameOf nl (Instance.pNode inst)) + m_nnm (Container.nameOf nl (Instance.sNode inst)) + header = printf "%2s %-*s %-*s %-*s" + " " m_name "Name" m_nnm "Pri_node" m_nnm "Sec_node"::String + in unlines (header:map helper sil) + -- | Shows statistics for a given node list. printStats :: Node.List -> String printStats nl = diff --git a/hbal.1 b/hbal.1 index 0f248962fec2198dc034d42527fa38f4ab1aed91..0c6b1d5a71592f82ce02b8925c06db304e29f7eb 100644 --- a/hbal.1 +++ b/hbal.1 @@ -33,6 +33,7 @@ Algorithm options: Reporting options: .BI "[ -C[" file "] ]" .B "[ -p ]" +.B "[ --print-instances ]" .B "[ -o ]" .B "[ -v... | -q ]" @@ -194,6 +195,11 @@ resource allocation in Ganeti) and thus we start a new jobset. Prints the before and after node status, in a format designed to allow the user to understand the node's most important parameters. +.TP +.B --print-instances +Prints the before and after instance map. This is less useful as the +node status, but it can help in understanding instance moves. + The node list will contain these informations: .RS .TP diff --git a/hbal.hs b/hbal.hs index e5dfd29a72b353dfb8fa6b4a93917fc23a889b15..f3d2e584a243798a958b2708dccc936ff2e35835 100644 --- a/hbal.hs +++ b/hbal.hs @@ -56,6 +56,7 @@ import Ganeti.Jobs options :: [OptType] options = [ oPrintNodes + , oPrintInsts , oPrintCommands , oOneline , oNodeFile @@ -227,6 +228,11 @@ main = do putStrLn "Cluster is not N+1 happy, continuing but no guarantee \ \that the cluster will end N+1 happy." + when (optShowInsts opts) $ do + putStrLn "" + putStrLn "Initial instance map:" + putStrLn $ Cluster.printInsts nl il + when (optShowNodes opts) $ do putStrLn "Initial cluster status:" @@ -257,7 +263,7 @@ main = do (fin_tbl, cmd_strs) <- iterateDepth ini_tbl (optMaxLength opts) (optDiskMoves opts) nmlen imlen [] oneline min_cv - let (Cluster.Table fin_nl _ fin_cv fin_plc) = fin_tbl + let (Cluster.Table fin_nl fin_il fin_cv fin_plc) = fin_tbl ord_plc = reverse fin_plc sol_msg = if null fin_plc then printf "No solution found\n" @@ -296,6 +302,11 @@ main = do exitWith $ ExitFailure 1 Just master -> execJobSet master csf fin_nl il cmd_jobs) + when (optShowInsts opts) $ do + putStrLn "" + putStrLn "Final instance map:" + putStr $ Cluster.printInsts fin_nl fin_il + when (optShowNodes opts) $ do let ini_cs = Cluster.totalResources nl