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

Add a command-line option to filter exclusion tags

Since we don't want all instance tags to be used for exclusion, we add a
command line option to filter on these. Since the iallocator protocol
cannot accept command line options, currently it's not possible to
specify these for hail, and thus it will never use any exclusion tags.
parent 5f0b9579
No related branches found
No related tags found
No related merge requests found
...@@ -59,6 +59,7 @@ module Ganeti.HTools.CLI ...@@ -59,6 +59,7 @@ module Ganeti.HTools.CLI
, oDiskMoves , oDiskMoves
, oDynuFile , oDynuFile
, oTieredSpec , oTieredSpec
, oExTags
, oShowVer , oShowVer
, oShowHelp , oShowHelp
) where ) where
...@@ -106,6 +107,7 @@ data Options = Options ...@@ -106,6 +107,7 @@ data Options = Options
, optMdsk :: Double -- ^ Max disk usage ratio for nodes , optMdsk :: Double -- ^ Max disk usage ratio for nodes
, optDiskMoves :: Bool -- ^ Allow disk moves , optDiskMoves :: Bool -- ^ Allow disk moves
, optDynuFile :: Maybe FilePath -- ^ Optional file with dynamic use data , optDynuFile :: Maybe FilePath -- ^ Optional file with dynamic use data
, optExTags :: Maybe [String] -- ^ Tags to use for exclusion
, optVerbose :: Int -- ^ Verbosity level , optVerbose :: Int -- ^ Verbosity level
, optShowVer :: Bool -- ^ Just show the program version , optShowVer :: Bool -- ^ Just show the program version
, optShowHelp :: Bool -- ^ Just show the help , optShowHelp :: Bool -- ^ Just show the help
...@@ -138,6 +140,7 @@ defaultOptions = Options ...@@ -138,6 +140,7 @@ defaultOptions = Options
, optMdsk = -1 , optMdsk = -1
, optDiskMoves = True , optDiskMoves = True
, optDynuFile = Nothing , optDynuFile = Nothing
, optExTags = Nothing
, optVerbose = 1 , optVerbose = 1
, optShowVer = False , optShowVer = False
, optShowHelp = False , optShowHelp = False
...@@ -293,6 +296,11 @@ oDynuFile = Option "U" ["dynu-file"] ...@@ -293,6 +296,11 @@ oDynuFile = Option "U" ["dynu-file"]
(ReqArg (\ f opts -> Ok 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"
oExTags :: OptType
oExTags = Option "" ["exclusion-tags"]
(ReqArg (\ f opts -> Ok opts { optExTags = Just $ sepSplit ',' f })
"TAG,...") "Enable instance exclusion based on given tag prefix"
oTieredSpec :: OptType oTieredSpec :: OptType
oTieredSpec = Option "" ["tiered-alloc"] oTieredSpec = Option "" ["tiered-alloc"]
(ReqArg (\ inp opts -> do (ReqArg (\ inp opts -> do
......
...@@ -98,6 +98,10 @@ loadExternalData opts = do ...@@ -98,6 +98,10 @@ loadExternalData opts = do
setSim = isJust simdata setSim = isJust simdata
setFiles = optNodeSet opts || optInstSet opts setFiles = optNodeSet opts || optInstSet opts
allSet = filter id [setRapi, setLuxi, setFiles] allSet = filter id [setRapi, setLuxi, setFiles]
exTags = case optExTags opts of
Nothing -> []
Just etl -> map (++ ":") etl
when (length allSet > 1) $ when (length allSet > 1) $
do do
hPutStrLn stderr ("Error: Only one of the rapi, luxi, and data" ++ hPutStrLn stderr ("Error: Only one of the rapi, luxi, and data" ++
...@@ -126,7 +130,7 @@ loadExternalData opts = do ...@@ -126,7 +130,7 @@ loadExternalData opts = do
| setSim -> Simu.loadData $ fromJust simdata | setSim -> Simu.loadData $ fromJust simdata
| otherwise -> wrapIO $ Text.loadData nodef instf | otherwise -> wrapIO $ Text.loadData nodef instf
let ldresult = input_data >>= Loader.mergeData util_data' let ldresult = input_data >>= Loader.mergeData util_data' exTags
(loaded_nl, il, csf) <- (loaded_nl, il, csf) <-
(case ldresult of (case ldresult of
Ok x -> return x Ok x -> return x
......
...@@ -110,7 +110,7 @@ parseData body = do ...@@ -110,7 +110,7 @@ parseData body = do
iobj <- mapM (\(x,y) -> iobj <- mapM (\(x,y) ->
asJSObject y >>= parseInstance ktn x . fromJSObject) idata asJSObject y >>= parseInstance ktn x . fromJSObject) idata
let (kti, il) = assignIndices iobj let (kti, il) = assignIndices iobj
(map_n, map_i, csf) <- mergeData [] (nl, il) (map_n, map_i, csf) <- mergeData [] [] (nl, il)
req_nodes <- fromObj "required_nodes" request req_nodes <- fromObj "required_nodes" request
optype <- fromObj "type" request optype <- fromObj "type" request
rqtype <- rqtype <-
......
...@@ -114,6 +114,14 @@ fixNodes accu inst = ...@@ -114,6 +114,14 @@ fixNodes accu inst =
in (sdx, snew):ac3 in (sdx, snew):ac3
else ac2 else ac2
-- | Remove non-selected tags from the exclusion list
filterExTags :: [String] -> Instance.Instance -> Instance.Instance
filterExTags tl inst =
let old_tags = Instance.tags inst
new_tags = filter (\tag -> any (\extag -> isPrefixOf extag tag) tl)
old_tags
in inst { Instance.tags = new_tags }
-- | Compute the longest common suffix of a list of strings that -- | Compute the longest common suffix of a list of strings that
-- | starts with a dot. -- | starts with a dot.
longestDomain :: [String] -> String longestDomain :: [String] -> String
...@@ -131,11 +139,12 @@ stripSuffix sflen name = take (length name - sflen) name ...@@ -131,11 +139,12 @@ stripSuffix sflen name = take (length name - sflen) name
-- | Initializer function that loads the data from a node and instance -- | Initializer function that loads the data from a node and instance
-- list and massages it into the correct format. -- list and massages it into the correct format.
mergeData :: [(String, DynUtil)] -- ^ Instance utilisation data mergeData :: [(String, DynUtil)] -- ^ Instance utilisation data
-> [String] -- ^ Exclusion tags
-> (Node.AssocList, -> (Node.AssocList,
Instance.AssocList) -- ^ Data from either Text.loadData Instance.AssocList) -- ^ Data from either Text.loadData
-- or Rapi.loadData -- or Rapi.loadData
-> Result (Node.List, Instance.List, String) -> Result (Node.List, Instance.List, String)
mergeData um (nl, il) = mergeData um extags (nl, il) =
let il2 = Container.fromAssocList il let il2 = Container.fromAssocList il
il3 = foldl' (\im (name, n_util) -> il3 = foldl' (\im (name, n_util) ->
case Container.findByName im name of case Container.findByName im name of
...@@ -144,15 +153,16 @@ mergeData um (nl, il) = ...@@ -144,15 +153,16 @@ mergeData um (nl, il) =
let new_i = inst { Instance.util = n_util } let new_i = inst { Instance.util = n_util }
in Container.add (Instance.idx inst) new_i im in Container.add (Instance.idx inst) new_i im
) il2 um ) il2 um
nl2 = foldl' fixNodes nl (Container.elems il3) il4 = Container.map (filterExTags extags) il3
nl2 = foldl' fixNodes nl (Container.elems il4)
nl3 = Container.fromAssocList nl3 = Container.fromAssocList
(map (\ (k, v) -> (k, Node.buildPeers v il3)) nl2) (map (\ (k, v) -> (k, Node.buildPeers v il4)) nl2)
node_names = map (Node.name . snd) nl node_names = map (Node.name . snd) nl
inst_names = map (Instance.name . snd) il inst_names = map (Instance.name . snd) il
common_suffix = longestDomain (node_names ++ inst_names) common_suffix = longestDomain (node_names ++ inst_names)
csl = length common_suffix csl = length common_suffix
snl = Container.map (\n -> setName n (stripSuffix csl $ nameOf n)) nl3 snl = Container.map (\n -> setName n (stripSuffix csl $ nameOf n)) nl3
sil = Container.map (\i -> setName i (stripSuffix csl $ nameOf i)) il3 sil = Container.map (\i -> setName i (stripSuffix csl $ nameOf i)) il4
in Ok (snl, sil, common_suffix) in Ok (snl, sil, common_suffix)
-- | Checks the cluster data for consistency. -- | Checks the cluster data for consistency.
......
...@@ -73,6 +73,7 @@ options = ...@@ -73,6 +73,7 @@ options =
, oMinDisk , oMinDisk
, oDiskMoves , oDiskMoves
, oDynuFile , oDynuFile
, oExTags
, oShowVer , oShowVer
, oShowHelp , oShowHelp
] ]
......
...@@ -137,7 +137,7 @@ main = do ...@@ -137,7 +137,7 @@ main = do
printf "%-*s " nlen name printf "%-*s " nlen name
hFlush stdout hFlush stdout
input_data <- Rapi.loadData name input_data <- Rapi.loadData name
let ldresult = input_data >>= Loader.mergeData [] let ldresult = input_data >>= Loader.mergeData [] []
(case ldresult of (case ldresult of
Bad err -> printf "\nError: failed to load data. \ Bad err -> printf "\nError: failed to load data. \
\Details:\n%s\n" err \Details:\n%s\n" err
......
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