, 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
dcKind :: DCKind
dcKind = DCKStatus
+-- | The report of this data collector.
+dcReport :: IO DCReport
+dcReport = buildInstStatusReport Nothing Nothing
+
-- * Command line options
options :: IO [OptType]
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
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