Hs2Py constants: add 'osApiVersions'
[ganeti-local] / src / Ganeti / DataCollectors / InstStatus.hs
index f3a8c1c..ed898d9 100644 (file)
@@ -32,18 +32,19 @@ module Ganeti.DataCollectors.InstStatus
   , dcFormatVersion
   , dcCategory
   , dcKind
+  , dcReport
   ) where
 
 
 import Control.Exception.Base
+import Data.List
 import Data.Maybe
 import qualified Data.Map as Map
 import Network.BSD (getHostName)
 import qualified Text.JSON as J
 
-import qualified Ganeti.BasicTypes as BT
-import Ganeti.Confd.Client
-import Ganeti.Confd.Types
+import Ganeti.BasicTypes as BT
+import Ganeti.Confd.ClientFunctions
 import Ganeti.Common
 import Ganeti.DataCollectors.CLI
 import Ganeti.DataCollectors.InstStatusTypes
@@ -77,6 +78,10 @@ dcCategory = Just DCInstance
 dcKind :: DCKind
 dcKind = DCKStatus
 
+-- | The report of this data collector.
+dcReport :: IO DCReport
+dcReport = buildInstStatusReport Nothing Nothing
+
 -- * Command line options
 
 options :: IO [OptType]
@@ -89,26 +94,6 @@ options = return
 arguments :: [ArgCompletion]
 arguments = []
 
--- | Get the list of instances ([primary], [secondary]) on the given node.
--- Implemented as a function, even if used a single time, to specify in a
--- convenient and elegant way the return data type, required in order to
--- prevent incurring in the monomorphism restriction.
--- The server address and the server port parameters are mainly intended
--- for testing purposes. If they are Nothing, the default values will be used.
-getInstances
-  :: String
-  -> Maybe String
-  -> Maybe Int
-  -> IO (BT.Result ([Ganeti.Objects.Instance], [Ganeti.Objects.Instance]))
-getInstances node srvAddr srvPort = do
-  client <- getConfdClient srvAddr srvPort
-  reply <- query client ReqNodeInstances $ PlainQuery node
-  return $
-    case fmap (J.readJSON . confdReplyAnswer) reply of
-      Just (J.Ok instances) -> BT.Ok instances
-      Just (J.Error msg) -> BT.Bad msg
-      Nothing -> BT.Bad "No answer from the Confd server"
-
 -- | Try to get the reason trail for an instance. In case it is not possible,
 -- log the failure and return an empty list instead.
 getReasonTrail :: String -> IO ReasonTrail
@@ -179,15 +164,41 @@ buildStatus domains uptimes inst = do
       trail
       status
 
+-- | Compute the status code and message, given the current DRBD data
+-- The final state will have the code corresponding to the worst code of
+-- all the devices, and the error message given from the concatenation of the
+-- non-empty error messages.
+computeGlobalStatus :: [InstStatus] -> DCStatus
+computeGlobalStatus instStatusList =
+  let dcstatuses = map iStatStatus instStatusList
+      statuses = map (\s -> (dcStatusCode s, dcStatusMessage s)) dcstatuses
+      (code, strList) = foldr mergeStatuses (DCSCOk, [""]) statuses
+  in DCStatus code $ intercalate "\n" strList
+
+-- | Build the report of this data collector, containing all the information
+-- about the status of the instances.
+buildInstStatusReport :: Maybe String -> Maybe Int -> IO DCReport
+buildInstStatusReport srvAddr srvPort = do
+  node <- getHostName
+  answer <- getInstances node srvAddr srvPort
+  inst <- exitIfBad "Can't get instance info from ConfD" answer
+  d <- getInferredDomInfo
+  reportData <-
+    case d of
+      BT.Ok domains -> do
+        uptimes <- getUptimeInfo
+        let primaryInst =  fst inst
+        iStatus <- mapM (buildStatus domains uptimes) primaryInst
+        let globalStatus = computeGlobalStatus iStatus
+        return $ ReportData iStatus globalStatus
+      BT.Bad m ->
+        return . ReportData [] . DCStatus DCSCBad $
+          "Unable to receive the list of instances: " ++ m
+  let jsonReport = J.showJSON reportData
+  buildReport dcName dcVersion dcFormatVersion dcCategory dcKind jsonReport
+
 -- | Main function.
 main :: Options -> [String] -> IO ()
 main opts _ = do
-  curNode <- getHostName
-  let node = fromMaybe curNode $ optNode opts
-  answer <- getInstances node (optConfdAddr opts) (optConfdPort opts)
-  inst <- exitIfBad "Can't get instance info from ConfD" answer
-  domains <- getInferredDomInfo
-  uptimes <- getUptimeInfo
-  let primaryInst =  fst inst
-  iStatus <- mapM (buildStatus domains uptimes) primaryInst
-  putStrLn $ J.encode iStatus
+  report <- buildInstStatusReport (optConfdAddr opts) (optConfdPort opts)
+  putStrLn $ J.encode report