Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / DataCollectors / InstStatus.hs @ fc4be2bf

History | View | Annotate | Download (4.7 kB)

1
{-| Instance status data collector.
2

    
3
-}
4

    
5
{-
6

    
7
Copyright (C) 2013 Google Inc.
8

    
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
13

    
14
This program is distributed in the hope that it will be useful, but
15
WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
General Public License for more details.
18

    
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22
02110-1301, USA.
23

    
24
-}
25

    
26
module Ganeti.DataCollectors.InstStatus
27
  ( main
28
  , options
29
  , arguments
30
  ) where
31

    
32

    
33
import Data.Maybe
34
import qualified Data.Map as Map
35
import Network.BSD (getHostName)
36
import qualified Text.JSON as J
37

    
38
import qualified Ganeti.BasicTypes as BT
39
import Ganeti.Confd.Client
40
import Ganeti.Confd.Types
41
import Ganeti.Common
42
import Ganeti.DataCollectors.CLI
43
import Ganeti.DataCollectors.InstStatusTypes
44
import Ganeti.DataCollectors.Types
45
import Ganeti.Hypervisor.Xen
46
import Ganeti.Hypervisor.Xen.Types
47
import Ganeti.Objects
48
import Ganeti.Utils
49

    
50
-- * Command line options
51

    
52
options :: IO [OptType]
53
options = return
54
  [ oConfdAddr
55
  , oConfdPort
56
  ]
57

    
58
-- | The list of arguments supported by the program.
59
arguments :: [ArgCompletion]
60
arguments = []
61

    
62
-- | Get the list of instances ([primary], [secondary]) on the given node.
63
-- Implemented as a function, even if used a single time, to specify in a
64
-- convenient and elegant way the return data type, required in order to
65
-- prevent incurring in the monomorphism restriction.
66
-- The server address and the server port parameters are mainly intended
67
-- for testing purposes. If they are Nothing, the default values will be used.
68
getInstances
69
  :: String
70
  -> Maybe String
71
  -> Maybe Int
72
  -> IO (BT.Result ([Ganeti.Objects.Instance], [Ganeti.Objects.Instance]))
73
getInstances node srvAddr srvPort = do
74
  client <- getConfdClient srvAddr srvPort
75
  reply <- query client ReqNodeInstances $ PlainQuery node
76
  return $
77
    case fmap (J.readJSON . confdReplyAnswer) reply of
78
      Just (J.Ok instances) -> BT.Ok instances
79
      Just (J.Error msg) -> BT.Bad msg
80
      Nothing -> BT.Bad "No answer from the Confd server"
81

    
82
-- | Determine the value of the status field for the report of one instance
83
computeStatusField :: AdminState -> ActualState -> DCStatus
84
computeStatusField AdminDown actualState =
85
  if actualState `notElem` [ActualShutdown, ActualDying]
86
    then DCStatus DCSCBad "The instance is not stopped as it should be"
87
    else DCStatus DCSCOk ""
88
computeStatusField AdminUp ActualHung =
89
  DCStatus DCSCUnknown "Instance marked as running, but it appears to be hung"
90
computeStatusField AdminUp actualState =
91
  if actualState `notElem` [ActualRunning, ActualBlocked]
92
    then DCStatus DCSCBad "The instance is not running as it should be"
93
    else DCStatus DCSCOk ""
94
computeStatusField AdminOffline _ =
95
  -- FIXME: The "offline" status seems not to be used anywhere in the source
96
  -- code, but it is defined, so we have to consider it anyway here.
97
  DCStatus DCSCUnknown "The instance is marked as offline"
98

    
99
-- Builds the status of an instance using runtime information about the Xen
100
-- Domains, their uptime information and the static information provided by
101
-- the ConfD server.
102
buildStatus :: Map.Map String Domain -> Map.Map Int UptimeInfo -> Instance
103
  -> IO InstStatus
104
buildStatus domains uptimes inst = do
105
  let name = instName inst
106
      currDomain = Map.lookup name domains
107
      idNum = fmap domId currDomain
108
      currUInfo = idNum >>= (`Map.lookup` uptimes)
109
      uptime = fmap uInfoUptime currUInfo
110
      adminState = instAdminState inst
111
      actualState =
112
        if adminState == AdminDown && isNothing currDomain
113
          then ActualShutdown
114
          else case currDomain of
115
            (Just dom@(Domain _ _ _ _ (Just isHung))) ->
116
              if isHung
117
                then ActualHung
118
                else domState dom
119
            _ -> ActualUnknown
120
      status = computeStatusField adminState actualState
121
  return $
122
    InstStatus
123
      name
124
      (instUuid inst)
125
      adminState
126
      actualState
127
      uptime
128
      (instMtime inst)
129
      status
130

    
131
-- | Main function.
132
main :: Options -> [String] -> IO ()
133
main opts _ = do
134
  curNode <- getHostName
135
  let node = fromMaybe curNode $ optNode opts
136
  answer <- getInstances node (optConfdAddr opts) (optConfdPort opts)
137
  inst <- exitIfBad "Can't get instance info from ConfD" answer
138
  domains <- getInferredDomInfo
139
  uptimes <- getUptimeInfo
140
  let primaryInst =  fst inst
141
  iStatus <- mapM (buildStatus domains uptimes) primaryInst
142
  putStrLn $ J.encode iStatus