On Tue, Sep 24, 2013 at 1:10 PM, Michele Tartara <[email protected]>wrote:

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

Also, please add tests.

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