On Fri, Sep 20, 2013 at 3:14 PM, Spyros Trigazis <[email protected]> wrote:

> Implement functionality to import MonD data from a mock file to
> HTools (mainly for testing purposes) with the --mond-data
> option.
>
> Signed-off-by: Spyros Trigazis <[email protected]>
> ---
>  src/Ganeti/HTools/CLI.hs          |   11 +++++++
>  src/Ganeti/HTools/ExtLoader.hs    |   65
> ++++++++++++++++++++++++++++++-------
>  src/Ganeti/HTools/Program/Hail.hs |    2 +-
>  src/Ganeti/HTools/Program/Hbal.hs |    1 +
>  4 files changed, 67 insertions(+), 12 deletions(-)
>
> diff --git a/src/Ganeti/HTools/CLI.hs b/src/Ganeti/HTools/CLI.hs
> index 12c3914..f4ca9fe 100644
> --- a/src/Ganeti/HTools/CLI.hs
> +++ b/src/Ganeti/HTools/CLI.hs
> @@ -48,6 +48,7 @@ module Ganeti.HTools.CLI
>    , oDiskTemplate
>    , oSpindleUse
>    , oDynuFile
> +  , oMonDDataFile
>    , oEvacMode
>    , oExInst
>    , oExTags
> @@ -123,6 +124,8 @@ data Options = Options
>    , optSpindleUse  :: Maybe Int      -- ^ Override for the spindle usage
>    , optDynuFile    :: Maybe FilePath -- ^ Optional file with dynamic use
> data
>    , optIgnoreDynu  :: Bool           -- ^ Do not use dynamic use data
> +  , optMonDDataFile :: Maybe FilePath -- ^ Optional file with data
> provided
> +                                     -- ^ by MonDs
>    , optEvacMode    :: Bool           -- ^ Enable evacuation mode
>    , optExInst      :: [String]       -- ^ Instances to be excluded
>    , optExTags      :: Maybe [String] -- ^ Tags to use for exclusion
> @@ -178,6 +181,7 @@ defaultOptions  = Options
>    , optSpindleUse  = Nothing
>    , optIgnoreDynu  = False
>    , optDynuFile    = Nothing
> +  , optMonDDataFile = Nothing
>    , optEvacMode    = False
>    , optExInst      = []
>    , optExTags      = Nothing
> @@ -280,6 +284,13 @@ oDiskMoves =
>     \ thus allowing only the 'cheap' failover/migrate operations",
>     OptComplNone)
>
> +oMonDDataFile :: OptType
> +oMonDDataFile =
> +  (Option "" ["mond-data"]
> +   (ReqArg (\ f opts -> Ok opts { optMonDDataFile = Just f }) "FILE")
> +   "Import data provided by MonDs from the given FILE",
> +   OptComplFile)
> +
>  oDiskTemplate :: OptType
>  oDiskTemplate =
>    (Option "" ["disk-template"]
> diff --git a/src/Ganeti/HTools/ExtLoader.hs
> b/src/Ganeti/HTools/ExtLoader.hs
> index d42c833..9086e91 100644
> --- a/src/Ganeti/HTools/ExtLoader.hs
> +++ b/src/Ganeti/HTools/ExtLoader.hs
> @@ -47,6 +47,8 @@ import System.Time (getClockTime)
>  import Text.Printf (hPrintf)
>
>  import qualified Text.JSON as J
> +import qualified Data.Map as Map
> +import qualified Data.List as L
>
>  import qualified Ganeti.Constants as C
>  import qualified Ganeti.DataCollectors.CPUload as CPUload
> @@ -131,7 +133,7 @@ loadExternalData opts = do
>        ldresult = input_data >>= (if ignoreDynU then clearDynU else return)
>                              >>= mergeData eff_u exTags selInsts exInsts
> now
>    cdata <- exitIfBad "failed to load data, aborting" ldresult
> -  cdata' <- if ignoreDynU then return cdata else queryAllMonDDCs cdata
> +  cdata' <- if ignoreDynU then return cdata else queryAllMonDDCs cdata
> opts
>

This will have to be changed as in the other patches.


>    let (fix_msgs, nl) = checkData (cdNodes cdata') (cdInstances cdata')
>
>    unless (optVerbose opts == 0) $ maybeShowWarnings fix_msgs
> @@ -166,18 +168,46 @@ collectors :: [DataCollector]
>  collectors =
>    [ DataCollector CPUload.dcName CPUload.dcCategory ]
>
> +-- | MonDs Data parsed by a mock file. Representing (node name, list of
> reports
> +-- produced by MonDs Data Collectors).
> +type MonDData = (String, [DCReport])
> +
> +-- | A map storing MonDs data.
> +type MapMonDData = Map.Map String [DCReport]
> +
> +-- | Parse MonD data file contents.
> +pMonDData :: String -> Result [MonDData]
> +pMonDData input =
> +  loadJSArray "Parsing MonD's answer" input >>=
> +  mapM (pMonDN . J.fromJSObject)
> +
> +-- | Parse a node's JSON record.
> +pMonDN :: JSRecord -> Result MonDData
> +pMonDN a = do
> +  node <- tryFromObj "Parsing node's name" a "node"
> +  reports <- tryFromObj "Parsing node's reports" a "reports"
> +  return (node, reports)
> +
>  -- | Query all MonDs for all Data Collector.
> -queryAllMonDDCs :: ClusterData -> IO ClusterData
> -queryAllMonDDCs cdata = do
> +queryAllMonDDCs :: ClusterData -> Options -> IO ClusterData
> +queryAllMonDDCs cdata opts = do
> +  map_mDD <-
> +    case optMonDDataFile opts of
> +      Nothing -> return Nothing
> +      Just fp -> do
> +        monDData_contents <- readFile fp
> +        monDData <- exitIfBad "can't parse MonD data"
> +                    . pMonDData $ monDData_contents
> +        return . Just $ Map.fromList monDData
>    let (ClusterData _ nl il _ _) = cdata
> -  (nl', il') <- foldM queryAllMonDs (nl, il) collectors
> +  (nl', il') <- foldM (queryAllMonDs map_mDD) (nl, il) collectors
>    return $ cdata {cdNodes = nl', cdInstances = il'}
>
>  -- | Query all MonDs for a single Data Collector.
> -queryAllMonDs :: (Node.List, Instance.List) -> DataCollector
> -                 -> IO (Node.List, Instance.List)
> -queryAllMonDs (nl, il) dc = do
> -  elems <- mapM (queryAMonD dc) (Container.elems nl)
> +queryAllMonDs :: Maybe MapMonDData -> (Node.List, Instance.List)
> +                 -> DataCollector -> IO (Node.List, Instance.List)
> +queryAllMonDs m (nl, il) dc = do
> +  elems <- mapM (queryAMonD m dc) (Container.elems nl)
>    let elems' = catMaybes elems
>    if length elems == length elems'
>      then do
> @@ -214,10 +244,23 @@ mkReport dc dcr =
>                  Bad _ -> Nothing
>            | otherwise -> Nothing
>
> +-- | Get data report for the specified Data Collector and Node from the
> map.
> +fromFile :: DataCollector -> Node.Node -> MapMonDData -> Maybe DCReport
> +fromFile dc node m =
> +  case Map.lookup (Node.name node) m of
> +    Nothing -> Nothing
> +    Just reports ->
> +      let matchDCName dcr = dName dc == dcReportName dcr
> +      in L.find matchDCName reports
> +
>  -- | Query a MonD for a single Data Collector.
> -queryAMonD :: DataCollector -> Node.Node -> IO (Maybe Node.Node)
> -queryAMonD dc node = do
> -  dcReport <- fromCurl dc node
> +queryAMonD :: Maybe MapMonDData -> DataCollector -> Node.Node
> +              -> IO (Maybe Node.Node)
> +queryAMonD m dc node = do
> +  dcReport <-
> +    case m of
> +      Nothing -> fromCurl dc node
> +      Just m' -> return $ fromFile dc node m'
>    case mkReport dc dcReport of
>      Nothing -> return Nothing
>      Just report ->
> diff --git a/src/Ganeti/HTools/Program/Hail.hs
> b/src/Ganeti/HTools/Program/Hail.hs
> index 507192c..b1e3653 100644
> --- a/src/Ganeti/HTools/Program/Hail.hs
> +++ b/src/Ganeti/HTools/Program/Hail.hs
> @@ -74,7 +74,7 @@ wrapReadRequest opts args = do
>      else do
>        let Request rqt cdata = r1
>        cdata' <-
> -        if optIgnoreDynu opts then return cdata else queryAllMonDDCs cdata
> +        if optIgnoreDynu opts then return cdata else queryAllMonDDCs
> cdata opts
>        return $ Request rqt cdata'
>
>  -- | Main function.
> diff --git a/src/Ganeti/HTools/Program/Hbal.hs
> b/src/Ganeti/HTools/Program/Hbal.hs
> index f863ad1..c385642 100644
> --- a/src/Ganeti/HTools/Program/Hbal.hs
> +++ b/src/Ganeti/HTools/Program/Hbal.hs
> @@ -92,6 +92,7 @@ options = do
>      , oInstMoves
>      , oDynuFile
>      , oIgnoreDyn
> +    , oMonDDataFile
>      , oExTags
>      , oExInst
>      , oSaveCluster
> --
> 1.7.10.4
>
>
Rest LGTM.

Thanks,
Michele

-- 
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