On Wed, Feb 25, 2015 at 01:58:46PM +0100, 'Klaus Aehlig' via ganeti-devel wrote:
Querying collectors might fail and for some collectors
the information might be incomplete. In this case, it might
be useful to continue with he information available, but this
is not necessarily the case. Therefore, provide the information
if the dynamic data collection was successful.

Signed-off-by: Klaus Aehlig <[email protected]>
---
src/Ganeti/HTools/Backend/MonD.hs | 24 +++++++++++++++---------
src/Ganeti/HTools/ExtLoader.hs    |  6 +++---
src/Ganeti/HTools/Program/Hail.hs |  5 +++--
3 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/src/Ganeti/HTools/Backend/MonD.hs 
b/src/Ganeti/HTools/Backend/MonD.hs
index bc85ff4..fb684ee 100644
--- a/src/Ganeti/HTools/Backend/MonD.hs
+++ b/src/Ganeti/HTools/Backend/MonD.hs
@@ -265,9 +265,10 @@ queryAMonD m dc node =
      Nothing -> fromCurl dc node
      Just m' -> return $ fromFile dc node m'

--- | Query all MonDs for a single Data Collector.
+-- | Query all MonDs for a single Data Collector. Return the updated
+-- cluster, as well as a bit inidicating wether the collector succeeded.
queryAllMonDs :: Maybe MapMonDData -> (Node.List, Instance.List)
-                 -> DataCollector -> IO (Node.List, Instance.List)
+                 -> DataCollector -> IO ((Node.List, Instance.List), Bool)
queryAllMonDs m (nl, il) dc = do
  elems <- mapM (queryAMonD m dc) (Container.elems nl)
  let elems' = catMaybes elems
@@ -275,17 +276,19 @@ queryAllMonDs m (nl, il) dc = do
    then
      let results = zip (Container.elems nl) elems'
      in case dUse dc results (nl, il) of
-        Ok (nl', il') -> return (nl', il')
+        Ok (nl', il') -> return ((nl', il'), True)
        Bad s -> do
          logWarning s
-          return (nl, il)
+          return ((nl, il), False)
    else do
      logWarning $ "Didn't receive an answer by all MonDs, " ++ dName dc
                   ++ "'s data will be ignored."
-      return (nl,il)
+      return ((nl,il), False)

--- | Query all MonDs for all Data Collector.
-queryAllMonDDCs :: ClusterData -> Options -> IO ClusterData
+-- | Query all MonDs for all Data Collector. Return the cluster enriched
+-- by dynamic data, as well as a bit indicating wether all collectors
+-- could be queried successfully.
+queryAllMonDDCs :: ClusterData -> Options -> IO (ClusterData, Bool)
queryAllMonDDCs cdata opts = do
  map_mDD <-
    case optMonDFile opts of
@@ -295,6 +298,9 @@ queryAllMonDDCs cdata opts = do
        monDData <- exitIfBad "can't parse MonD data"
                    . pMonDData $ monDData_contents
        return . Just $ Map.fromList monDData
+  let query (cluster, ok) collector  = do
+        (cluster', ok') <- queryAllMonDs map_mDD cluster collector
+        return (cluster', ok && ok')
  let (ClusterData _ nl il _ _) = cdata
-  (nl', il') <- foldM (queryAllMonDs map_mDD) (nl, il) (collectors opts)
-  return $ cdata {cdNodes = nl', cdInstances = il'}
+  ((nl', il'), ok) <- foldM query ((nl, il), True) (collectors opts)
+  return (cdata {cdNodes = nl', cdInstances = il'}, ok)
diff --git a/src/Ganeti/HTools/ExtLoader.hs b/src/Ganeti/HTools/ExtLoader.hs
index cdc81eb..18b1563 100644
--- a/src/Ganeti/HTools/ExtLoader.hs
+++ b/src/Ganeti/HTools/ExtLoader.hs
@@ -124,9 +124,9 @@ 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 optMonD opts
-              then MonD.queryAllMonDDCs cdata opts
-              else return cdata
+  (cdata', _) <- if optMonD opts
+                   then MonD.queryAllMonDDCs cdata opts
+                   else return (cdata, True)
  let (fix_msgs, nl) = checkData (cdNodes cdata') (cdInstances cdata')

  unless (optVerbose opts == 0) $ maybeShowWarnings fix_msgs
diff --git a/src/Ganeti/HTools/Program/Hail.hs 
b/src/Ganeti/HTools/Program/Hail.hs
index 2a398ad..1d57f17 100644
--- a/src/Ganeti/HTools/Program/Hail.hs
+++ b/src/Ganeti/HTools/Program/Hail.hs
@@ -87,8 +87,9 @@ wrapReadRequest opts args = do
      return $ Request rqt cdata
    else do
      let Request rqt cdata = r1
-      cdata' <-
-        if optMonD opts then MonD.queryAllMonDDCs cdata opts else return cdata
+      (cdata', _) <- if optMonD opts
+                       then MonD.queryAllMonDDCs cdata opts
+                       else return (cdata, True)
      return $ Request rqt cdata'

-- | Main function.
--
2.2.0.rc0.207.ga3a616c


LGTM

A suggestion for discussion: Adding the 'Bool' parameters obscures a bit the code, as it needs to be dealt with at various places. What about using

  WriterT All IO a

(perhaps as a type alias for easier refactoring, if needed) instead of

  IO (a, Bool)

? Reporting a failure is then just calling `tell (All False)` and a lot of the existing code (foldM etc) would remain unchanged, without needing to explicitly process the boolean part, making the && implicit. On the other hand, it requires adding liftIO at a few places and also at the place where the whole query is run.

Reply via email to