On Thu, Oct 31, 2013 at 2:58 PM, Klaus Aehlig <[email protected]> wrote:

> If the amount of free resources falls below a given threshold,
> hsqueeze will suggest putting standby nodes back online until
> the minimum of free resources is reached, or all standby nodes
> are online.
>
> Signed-off-by: Klaus Aehlig <[email protected]>
> ---
>  src/Ganeti/HTools/Program/Hsqueeze.hs | 129
> ++++++++++++++++++++++++++--------
>  1 file changed, 99 insertions(+), 30 deletions(-)
>
> diff --git a/src/Ganeti/HTools/Program/Hsqueeze.hs
> b/src/Ganeti/HTools/Program/Hsqueeze.hs
> index ca2b8a7..1827804 100644
> --- a/src/Ganeti/HTools/Program/Hsqueeze.hs
> +++ b/src/Ganeti/HTools/Program/Hsqueeze.hs
> @@ -55,6 +55,7 @@ options = do
>    return
>      [ luxi
>      , oDataFile
> +    , oMinResources
>      , oTargetResources
>      , oSaveCluster
>      , oVerbose
> @@ -65,6 +66,15 @@ options = do
>  arguments :: [ArgCompletion]
>  arguments = []
>
> +-- | The tag-prefix indicating that hsqueeze should consider a node
> +-- as being standy.
> +standbyPrefix :: String
> +standbyPrefix = "htools:standby:"
> +
> +-- | Predicate of having a standy tag.
>

typo: standby


> +hasStandbyTag :: Node.Node -> Bool
> +hasStandbyTag = any (standbyPrefix `isPrefixOf`) . Node.nTags
> +
>  -- | Within a cluster configuration, decide if the node hosts only
>  -- externally-mirrored instances.
>  onlyExternal ::  (Node.List, Instance.List) -> Node.Node -> Bool
> @@ -98,30 +108,53 @@ balance (nl, il) =
>                                      $ iterate (>>= balanceStep) (Just
> ini_tbl)
>    in (nl', il')
>
> --- | In a configuration, mark a node as offline.
> -offlineNode :: (Node.List, Instance.List) -> Ndx -> (Node.List,
> Instance.List)
> -offlineNode (nl, il) ndx =
> +-- | In a configuration, mark a node as online or offline.
> +onlineOfflineNode :: Bool -> (Node.List, Instance.List) -> Ndx ->
> +                     (Node.List, Instance.List)
> +onlineOfflineNode offline (nl, il) ndx =
>    let nd = Container.find ndx nl
> -      nd' = Node.setOffline nd True
> +      nd' = Node.setOffline nd offline
>        nl' = Container.add ndx nd' nl
>    in (nl', il)
>
> --- | Offline a list node, and return the state after a balancing attempt.
> -offlineNodes :: [Ndx] -> (Node.List, Instance.List)
> -                -> (Node.List, Instance.List)
> -offlineNodes ndxs conf =
> -  let conf' = foldl offlineNode conf ndxs
> +-- | Offline or online a list nodes, and return the state after a
> balancing
> +-- attempt.
> +onlineOfflineNodes :: Bool -> [Ndx] -> (Node.List, Instance.List)
> +                      -> (Node.List, Instance.List)
> +onlineOfflineNodes offline ndxs conf =
> +  let conf' = foldl (onlineOfflineNode offline) conf ndxs
>    in balance conf'
>
> --- | Predicate on whether a list of nodes can be offlined simultaneously
> in a
> --- given configuration, while still leaving enough capacity on every node
> for
> --- the given instance
> -canOffline :: Instance.Instance -> [Node.Node] -> (Node.List,
> Instance.List)
> -              -> Bool
> -canOffline inst nds conf =
> -  let conf' = offlineNodes (map Node.idx nds) conf
> +-- | Offline a list of nodes, and return the state after balancing.
> +offlineNodes :: [Ndx] -> (Node.List, Instance.List)
> +                -> (Node.List, Instance.List)
> +offlineNodes = onlineOfflineNodes True
> +
> +-- | Online a list of nodes, and return the state after balancing.
> +onlineNodes :: [Ndx] -> (Node.List, Instance.List)
> +               -> (Node.List, Instance.List)
> +onlineNodes = onlineOfflineNodes False
> +
> +-- | Predicate on whether a list of nodes can be offlined or onlines
>

type: onlined


> +-- simultaneously in a given configuration, while still leaving enough
> +-- capacity on every node for the given instance.
> +canOnlineOffline :: Bool -> Instance.Instance -> (Node.List,
> Instance.List)
> +                    -> [Node.Node] ->Bool
> +canOnlineOffline offline inst conf nds =
> +  let conf' = onlineOfflineNodes offline (map Node.idx nds) conf
>    in allInstancesOnOnlineNodes conf' && allNodesCapacityFor inst conf'
>
> +-- | Predicate on whether a list of nodes can be offlined simultaneously.
> +canOffline :: Instance.Instance -> (Node.List, Instance.List) ->
> +              [Node.Node] -> Bool
> +canOffline = canOnlineOffline True
> +
> +-- | Predicate on wheter onlining a list of lnodes suffices to get enough
>

typo: whether

s/Inodes/nodes ?


> +-- free resources for given instance.
> +sufficesOnline :: Instance.Instance -> (Node.List, Instance.List)
> +                  -> [Node.Node] ->  Bool
> +sufficesOnline = canOnlineOffline False
> +
>  -- | Greedily offline the nodes, starting from the last element, and
> return
>  -- the list of nodes that could simultaneously be offlined, while keeping
>  -- the resources specified by an instance.
> @@ -130,7 +163,14 @@ greedyOfflineNodes :: Instance.Instance ->
> (Node.List, Instance.List)
>  greedyOfflineNodes _ _ [] = []
>  greedyOfflineNodes inst conf (nd:nds) =
>    let nds' = greedyOfflineNodes inst conf nds
> -  in if canOffline inst (nd:nds') conf then nd:nds' else nds'
> +  in if canOffline inst conf (nd:nds') then nd:nds' else nds'
> +
> +-- | Try to provide enough resources by onlining an initial segment of
> +-- a list of nodes. Return Nothing, if even onlining all of them is not
> +-- enough.
> +tryOnline :: Instance.Instance -> (Node.List, Instance.List) ->
> [Node.Node]
> +             -> Maybe [Node.Node]
> +tryOnline inst conf = listToMaybe . filter (sufficesOnline inst conf) .
> inits
>
>  -- | From a specification, name, and factor create an instance that uses
> that
>  -- factor times the specification, rounded down.
> @@ -151,35 +191,64 @@ main opts args = do
>
>    let verbose = optVerbose opts
>        targetf = optTargetResources opts
> +      minf = optMinResources opts
>
>    ini_cdata@(ClusterData _ nlf ilf _ ipol) <- loadExternalData opts
>
>    maybeSaveData (optSaveCluster opts) "original" "before hsqueeze run"
> ini_cdata
>
> -  let offlineCandidates =
> +  let nodelist = IntMap.elems nlf
> +      offlineCandidates =
>          sortBy (flip compare `on` length . Node.pList)
>          . filter (foldl (liftA2 (&&)) (const True)
>                    [ not . Node.offline
>                    , not . Node.isMaster
>                    , onlyExternal (nlf, ilf)
>                    ])
> -        . IntMap.elems $ nlf
> +        $ nodelist
> +      onlineCandidates =
> +        filter (liftA2 (&&) Node.offline hasStandbyTag) nodelist
>        conf = (nlf, ilf)
>        std = iPolicyStdSpec ipol
>        targetInstance = instanceFromSpecAndFactor "targetInstance" targetf
> std
> +      minInstance = instanceFromSpecAndFactor "targetInstance" minf std
>        toOffline = greedyOfflineNodes targetInstance conf offlineCandidates
> -      (fin_nl, fin_il) = offlineNodes (map Node.idx toOffline) conf
> -      final_cdata = ini_cdata { cdNodes = fin_nl, cdInstances = fin_il }
> +      (fin_off_nl, fin_off_il) = offlineNodes (map Node.idx toOffline)
> conf
> +      final_off_cdata =
> +        ini_cdata { cdNodes = fin_off_nl, cdInstances = fin_off_il }
> +      toOnline = tryOnline minInstance conf onlineCandidates
> +      nodesToOnline = fromMaybe onlineCandidates toOnline
> +      (fin_on_nl, fin_on_il) = onlineNodes (map Node.idx nodesToOnline)
> conf
> +      final_on_cdata =
> +        ini_cdata { cdNodes = fin_on_nl, cdInstances = fin_on_il }
>
>    when (verbose > 1) . putStrLn
>      $ "Offline candidates: " ++ commaJoin (map Node.name
> offlineCandidates)
>
> -  unless (optNoHeaders opts) $
> -    putStrLn "'Nodes to offline'"
> -
> -  mapM_ (putStrLn . Node.name) toOffline
> -
> -  maybeSaveData (optSaveCluster opts)
> -    "squeezed" "after hsqueeze run" final_cdata
> -
> -
> +  when (verbose > 1) . putStrLn
> +    $ "Online candidates: " ++ commaJoin (map Node.name onlineCandidates)
> +
> +  if not (allNodesCapacityFor minInstance conf)
> +    then do
> +      unless (optNoHeaders opts) $
> +        putStrLn "'Nodes to online'"
> +      mapM_ (putStrLn . Node.name) nodesToOnline
> +      when (verbose > 1 && isNothing toOnline) . putStrLn $
> +        "Onlining all nodes will not yield enough capacity"
> +      maybeSaveData (optSaveCluster opts)
> +         "squeezed" "after hsqueeze expansion" final_on_cdata
> +    else
> +      if null toOffline
> +        then do
> +          unless (optNoHeaders opts) $
> +            putStrLn "'No action'"
> +          maybeSaveData (optSaveCluster opts)
> +            "squeezed" "after hsqueeze doing nothing" ini_cdata
> +        else do
> +          unless (optNoHeaders opts) $
> +            putStrLn "'Nodes to offline'"
> +
> +          mapM_ (putStrLn . Node.name) toOffline
> +
> +          maybeSaveData (optSaveCluster opts)
> +            "squeezed" "after hsqueeze run" final_off_cdata
> --
> 1.8.4.1
>
>
Rest, LGTM

-- 
-- 
Helga Velroyen | Software Engineer | [email protected] |

Google Germany GmbH
Dienerstr. 12
80331 München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores

Reply via email to