diff --git a/src/Ganeti/HTools/CLI.hs b/src/Ganeti/HTools/CLI.hs index 5e9bf084006cb992172053437b96bc49548e5711..8f55f6fb40489d2f64e5427bf5d7d80c697a3e4e 100644 --- a/src/Ganeti/HTools/CLI.hs +++ b/src/Ganeti/HTools/CLI.hs @@ -52,6 +52,7 @@ module Ganeti.HTools.CLI , oExInst , oExTags , oExecJobs + , oForce , oGroup , oIAllocSrc , oInstMoves @@ -117,6 +118,7 @@ data Options = Options , optExInst :: [String] -- ^ Instances to be excluded , optExTags :: Maybe [String] -- ^ Tags to use for exclusion , optExecJobs :: Bool -- ^ Execute the commands via Luxi + , optForce :: Bool -- ^ Force the execution , optGroup :: Maybe GroupID -- ^ The UUID of the group to process , optIAllocSrc :: Maybe FilePath -- ^ The iallocation spec , optSelInst :: [String] -- ^ Instances to be excluded @@ -163,6 +165,7 @@ defaultOptions = Options , optExInst = [] , optExTags = Nothing , optExecJobs = False + , optForce = False , optGroup = Nothing , optIAllocSrc = Nothing , optSelInst = [] @@ -319,6 +322,14 @@ oExecJobs = \ it for data gathering)", OptComplNone) +oForce :: OptType +oForce = + (Option "f" ["force"] + (NoArg (\ opts -> Ok opts {optForce = True})) + "force the execution of this program, even if warnings would\ + \ otherwise prevent it", + OptComplNone) + oGroup :: OptType oGroup = (Option "G" ["group"] diff --git a/src/Ganeti/HTools/Program/Hroller.hs b/src/Ganeti/HTools/Program/Hroller.hs index e5584900365f2f17475e6aede13894508ca6dd90..72e863287eac6d40784ca78f5f0d6baca45e2852 100644 --- a/src/Ganeti/HTools/Program/Hroller.hs +++ b/src/Ganeti/HTools/Program/Hroller.hs @@ -61,6 +61,7 @@ options = do , oNoHeaders , oSaveCluster , oGroup + , oForce ] -- | The list of arguments supported by the program. @@ -112,11 +113,19 @@ main opts args = do unless (null args) $ exitErr "This program doesn't take any arguments." let verbose = optVerbose opts + maybeExit = if optForce opts then warn else exitErr -- Load cluster data. The last two arguments, cluster tags and ipolicy, are -- currently not used by this tool. ini_cdata@(ClusterData gl fixed_nl ilf _ _) <- loadExternalData opts + let master_names = map Node.name . filter Node.isMaster . IntMap.elems $ + fixed_nl + case master_names of + [] -> maybeExit "No master node found (maybe not supported by backend)." + [ _ ] -> return () + _ -> exitErr $ "Found more than one master node: " ++ show master_names + nlf <- setNodeStatus opts fixed_nl maybeSaveData (optSaveCluster opts) "original" "before hroller run" ini_cdata diff --git a/src/Ganeti/Utils.hs b/src/Ganeti/Utils.hs index b4a8c3cacfbadee13e0c265399ccfb8e1903b5a9..89a054d9e602d432239d9e0adef650cb06cf57df 100644 --- a/src/Ganeti/Utils.hs +++ b/src/Ganeti/Utils.hs @@ -49,6 +49,7 @@ module Ganeti.Utils , getCurrentTimeUSec , clockTimeToString , chompPrefix + , warn , wrap , trim , defaultHead @@ -247,6 +248,10 @@ exitWhen False _ = return () exitUnless :: Bool -> String -> IO () exitUnless cond = exitWhen (not cond) +-- | Print a warning, but do not exit. +warn :: String -> IO () +warn = hPutStrLn stderr . (++) "Warning: " + -- | Helper for 'niceSort'. Computes the key element for a given string. extractKey :: [Either Integer String] -- ^ Current (partial) key, reversed -> String -- ^ Remaining string diff --git a/test/hs/shelltests/htools-invalid.test b/test/hs/shelltests/htools-invalid.test index eabce21bed8ac8e7213b945b61a8cb3a768e69df..c2bbe3e3e9bbb26623c097e5a09946795b2c9dd1 100644 --- a/test/hs/shelltests/htools-invalid.test +++ b/test/hs/shelltests/htools-invalid.test @@ -52,10 +52,14 @@ Error: This program doesn't take any arguments. Error: This program doesn't take any arguments. >>>=1 -# hroller fails to build a graph for an empty cluster +# hroller should notice the absence of a master node ./test/hs/hroller -t$TESTDATA_DIR/empty-cluster.data ->>>2 -Error: Cannot create node graph +>>>2/Error: No master node found/ +>>>=1 + +# hroller fails to build a graph for an empty cluster +./test/hs/hroller -f -t$TESTDATA_DIR/empty-cluster.data +>>>2/Error: Cannot create node graph/ >>>=1 # hbal doesn't accept invalid priority diff --git a/test/hs/shelltests/htools-single-group.test b/test/hs/shelltests/htools-single-group.test index f8e629cb5eb0b9abc587389a0a004d7d9dfaf123..0f271320e5e084178ed28d71e32caebbc1b8f480 100644 --- a/test/hs/shelltests/htools-single-group.test +++ b/test/hs/shelltests/htools-single-group.test @@ -28,10 +28,12 @@ >>> /HCHECK_INIT_CLUSTER_NEED_REBALANCE=0/ >>>= 0 +# FIXME: remove option -f once the text backend supports indicating +# the master node # hroller should be able to print the solution -./test/hs/hroller -t$T/simu-onegroup.tiered +./test/hs/hroller -f -t$T/simu-onegroup.tiered >>>= 0 # hroller should be able to print the solution, in verbose mode as well -./test/hs/hroller -t$T/simu-onegroup.tiered -v -v +./test/hs/hroller -f -t$T/simu-onegroup.tiered -v -v >>>= 0