Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Rpc.hs @ 1ca709c1

History | View | Annotate | Download (15.2 kB)

1 1ca709c1 Iustin Pop
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,
2 96dad12d Agata Murawska
  BangPatterns, TemplateHaskell #-}
3 d4709cce Agata Murawska
4 d4709cce Agata Murawska
{-| Implementation of the RPC client.
5 d4709cce Agata Murawska
6 d4709cce Agata Murawska
-}
7 d4709cce Agata Murawska
8 d4709cce Agata Murawska
{-
9 d4709cce Agata Murawska
10 1ca709c1 Iustin Pop
Copyright (C) 2012, 2013 Google Inc.
11 d4709cce Agata Murawska
12 d4709cce Agata Murawska
This program is free software; you can redistribute it and/or modify
13 d4709cce Agata Murawska
it under the terms of the GNU General Public License as published by
14 d4709cce Agata Murawska
the Free Software Foundation; either version 2 of the License, or
15 d4709cce Agata Murawska
(at your option) any later version.
16 d4709cce Agata Murawska
17 d4709cce Agata Murawska
This program is distributed in the hope that it will be useful, but
18 d4709cce Agata Murawska
WITHOUT ANY WARRANTY; without even the implied warranty of
19 d4709cce Agata Murawska
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 d4709cce Agata Murawska
General Public License for more details.
21 d4709cce Agata Murawska
22 d4709cce Agata Murawska
You should have received a copy of the GNU General Public License
23 d4709cce Agata Murawska
along with this program; if not, write to the Free Software
24 d4709cce Agata Murawska
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 d4709cce Agata Murawska
02110-1301, USA.
26 d4709cce Agata Murawska
27 d4709cce Agata Murawska
-}
28 d4709cce Agata Murawska
29 d4709cce Agata Murawska
module Ganeti.Rpc
30 d4709cce Agata Murawska
  ( RpcCall
31 d4709cce Agata Murawska
  , Rpc
32 d4709cce Agata Murawska
  , RpcError(..)
33 599239ad Agata Murawska
  , ERpcError
34 60443f61 Agata Murawska
  , explainRpcError
35 eaed5f19 Agata Murawska
  , executeRpcCall
36 d4709cce Agata Murawska
37 d4709cce Agata Murawska
  , rpcCallName
38 d4709cce Agata Murawska
  , rpcCallTimeout
39 d4709cce Agata Murawska
  , rpcCallData
40 d4709cce Agata Murawska
  , rpcCallAcceptOffline
41 d4709cce Agata Murawska
42 d4709cce Agata Murawska
  , rpcResultFill
43 96dad12d Agata Murawska
44 96dad12d Agata Murawska
  , InstanceInfo(..)
45 5188fdb7 Agata Murawska
  , RpcCallInstanceInfo(..)
46 5188fdb7 Agata Murawska
  , RpcResultInstanceInfo(..)
47 5188fdb7 Agata Murawska
48 96dad12d Agata Murawska
  , RpcCallAllInstancesInfo(..)
49 96dad12d Agata Murawska
  , RpcResultAllInstancesInfo(..)
50 96dad12d Agata Murawska
51 c1c5aab1 Agata Murawska
  , RpcCallInstanceList(..)
52 c1c5aab1 Agata Murawska
  , RpcResultInstanceList(..)
53 c1c5aab1 Agata Murawska
54 dc623a95 Agata Murawska
  , HvInfo(..)
55 dc623a95 Agata Murawska
  , VgInfo(..)
56 dc623a95 Agata Murawska
  , RpcCallNodeInfo(..)
57 dc623a95 Agata Murawska
  , RpcResultNodeInfo(..)
58 dc623a95 Agata Murawska
59 8779d21a Agata Murawska
  , RpcCallVersion(..)
60 8779d21a Agata Murawska
  , RpcResultVersion(..)
61 8779d21a Agata Murawska
62 47163f0f Agata Murawska
  , StorageField(..)
63 47163f0f Agata Murawska
  , RpcCallStorageList(..)
64 47163f0f Agata Murawska
  , RpcResultStorageList(..)
65 47163f0f Agata Murawska
66 de2a5704 Iustin Pop
  , RpcCallTestDelay(..)
67 de2a5704 Iustin Pop
  , RpcResultTestDelay(..)
68 de2a5704 Iustin Pop
69 96dad12d Agata Murawska
  , rpcTimeoutFromRaw -- FIXME: Not used anywhere
70 d4709cce Agata Murawska
  ) where
71 d4709cce Agata Murawska
72 9b09c0be Agata Murawska
import Control.Arrow (second)
73 319322a7 Bernardo Dal Seno
import qualified Data.Map as Map
74 319322a7 Bernardo Dal Seno
import Data.Maybe (fromMaybe)
75 d4709cce Agata Murawska
import qualified Text.JSON as J
76 9b09c0be Agata Murawska
import Text.JSON.Pretty (pp_value)
77 d4709cce Agata Murawska
78 eaed5f19 Agata Murawska
import Network.Curl
79 7766de33 Agata Murawska
import qualified Ganeti.Path as P
80 eaed5f19 Agata Murawska
81 eaed5f19 Agata Murawska
import qualified Ganeti.Constants as C
82 d4709cce Agata Murawska
import Ganeti.Objects
83 96dad12d Agata Murawska
import Ganeti.THH
84 22381768 Iustin Pop
import Ganeti.Types
85 f3baf5ef Iustin Pop
import Ganeti.Compat
86 eaed5f19 Agata Murawska
87 de2a5704 Iustin Pop
-- * Base RPC functionality and types
88 de2a5704 Iustin Pop
89 eaed5f19 Agata Murawska
-- | The curl options used for RPC.
90 eaed5f19 Agata Murawska
curlOpts :: [CurlOption]
91 eaed5f19 Agata Murawska
curlOpts = [ CurlFollowLocation False
92 eaed5f19 Agata Murawska
           , CurlSSLVerifyHost 0
93 eaed5f19 Agata Murawska
           , CurlSSLVerifyPeer True
94 eaed5f19 Agata Murawska
           , CurlSSLCertType "PEM"
95 eaed5f19 Agata Murawska
           , CurlSSLKeyType "PEM"
96 eaed5f19 Agata Murawska
           , CurlConnectTimeout (fromIntegral C.rpcConnectTimeout)
97 eaed5f19 Agata Murawska
           ]
98 d4709cce Agata Murawska
99 d4709cce Agata Murawska
-- | Data type for RPC error reporting.
100 d4709cce Agata Murawska
data RpcError
101 1ca709c1 Iustin Pop
  = CurlLayerError Node String
102 d4709cce Agata Murawska
  | JsonDecodeError String
103 6fddde87 Agata Murawska
  | RpcResultError String
104 d4709cce Agata Murawska
  | OfflineNodeError Node
105 60443f61 Agata Murawska
  deriving (Show, Eq)
106 d4709cce Agata Murawska
107 60443f61 Agata Murawska
-- | Provide explanation to RPC errors.
108 60443f61 Agata Murawska
explainRpcError :: RpcError -> String
109 60443f61 Agata Murawska
explainRpcError (CurlLayerError node code) =
110 6fddde87 Agata Murawska
    "Curl error for " ++ nodeName node ++ ", " ++ code
111 60443f61 Agata Murawska
explainRpcError (JsonDecodeError msg) =
112 6fddde87 Agata Murawska
    "Error while decoding JSON from HTTP response: " ++ msg
113 60443f61 Agata Murawska
explainRpcError (RpcResultError msg) =
114 6fddde87 Agata Murawska
    "Error reponse received from RPC server: " ++ msg
115 60443f61 Agata Murawska
explainRpcError (OfflineNodeError node) =
116 d4709cce Agata Murawska
    "Node " ++ nodeName node ++ " is marked as offline"
117 d4709cce Agata Murawska
118 599239ad Agata Murawska
type ERpcError = Either RpcError
119 599239ad Agata Murawska
120 96dad12d Agata Murawska
-- | Basic timeouts for RPC calls.
121 96dad12d Agata Murawska
$(declareIADT "RpcTimeout"
122 96dad12d Agata Murawska
  [ ( "Urgent",    'C.rpcTmoUrgent )
123 96dad12d Agata Murawska
  , ( "Fast",      'C.rpcTmoFast )
124 96dad12d Agata Murawska
  , ( "Normal",    'C.rpcTmoNormal )
125 96dad12d Agata Murawska
  , ( "Slow",      'C.rpcTmoSlow )
126 96dad12d Agata Murawska
  , ( "FourHours", 'C.rpcTmo4hrs )
127 96dad12d Agata Murawska
  , ( "OneDay",    'C.rpcTmo1day )
128 96dad12d Agata Murawska
  ])
129 96dad12d Agata Murawska
130 d4709cce Agata Murawska
-- | A generic class for RPC calls.
131 d4709cce Agata Murawska
class (J.JSON a) => RpcCall a where
132 d4709cce Agata Murawska
  -- | Give the (Python) name of the procedure.
133 d4709cce Agata Murawska
  rpcCallName :: a -> String
134 d4709cce Agata Murawska
  -- | Calculate the timeout value for the call execution.
135 d4709cce Agata Murawska
  rpcCallTimeout :: a -> Int
136 d4709cce Agata Murawska
  -- | Prepare arguments of the call to be send as POST.
137 d4709cce Agata Murawska
  rpcCallData :: Node -> a -> String
138 d4709cce Agata Murawska
  -- | Whether we accept offline nodes when making a call.
139 d4709cce Agata Murawska
  rpcCallAcceptOffline :: a -> Bool
140 d4709cce Agata Murawska
141 d4709cce Agata Murawska
-- | Generic class that ensures matching RPC call with its respective
142 d4709cce Agata Murawska
-- result.
143 47163f0f Agata Murawska
class (RpcCall a, J.JSON b) => Rpc a b  | a -> b, b -> a where
144 47163f0f Agata Murawska
  -- | Create a result based on the received HTTP response.
145 a93b711b Agata Murawska
  rpcResultFill :: a -> J.JSValue -> ERpcError b
146 eaed5f19 Agata Murawska
147 eaed5f19 Agata Murawska
-- | Http Request definition.
148 eaed5f19 Agata Murawska
data HttpClientRequest = HttpClientRequest
149 eaed5f19 Agata Murawska
  { requestTimeout :: Int
150 eaed5f19 Agata Murawska
  , requestUrl :: String
151 eaed5f19 Agata Murawska
  , requestPostData :: String
152 eaed5f19 Agata Murawska
  }
153 eaed5f19 Agata Murawska
154 eaed5f19 Agata Murawska
-- | Execute the request and return the result as a plain String. When
155 eaed5f19 Agata Murawska
-- curl reports an error, we propagate it.
156 599239ad Agata Murawska
executeHttpRequest :: Node -> ERpcError HttpClientRequest
157 599239ad Agata Murawska
                   -> IO (ERpcError String)
158 eaed5f19 Agata Murawska
159 eaed5f19 Agata Murawska
executeHttpRequest _ (Left rpc_err) = return $ Left rpc_err
160 eaed5f19 Agata Murawska
executeHttpRequest node (Right request) = do
161 29a30533 Iustin Pop
  cert_file <- P.nodedCertFile
162 eaed5f19 Agata Murawska
  let reqOpts = [ CurlTimeout (fromIntegral $ requestTimeout request)
163 eaed5f19 Agata Murawska
                , CurlPostFields [requestPostData request]
164 29a30533 Iustin Pop
                , CurlSSLCert cert_file
165 29a30533 Iustin Pop
                , CurlSSLKey cert_file
166 29a30533 Iustin Pop
                , CurlCAInfo cert_file
167 eaed5f19 Agata Murawska
                ]
168 eaed5f19 Agata Murawska
      url = requestUrl request
169 eaed5f19 Agata Murawska
  -- FIXME: This is very similar to getUrl in Htools/Rapi.hs
170 eaed5f19 Agata Murawska
  (code, !body) <- curlGetString url $ curlOpts ++ reqOpts
171 2cdaf225 Iustin Pop
  return $ case code of
172 2cdaf225 Iustin Pop
             CurlOK -> Right body
173 2cdaf225 Iustin Pop
             _ -> Left $ CurlLayerError node (show code)
174 eaed5f19 Agata Murawska
175 eaed5f19 Agata Murawska
-- | Prepare url for the HTTP request.
176 eaed5f19 Agata Murawska
prepareUrl :: (RpcCall a) => Node -> a -> String
177 eaed5f19 Agata Murawska
prepareUrl node call =
178 eaed5f19 Agata Murawska
  let node_ip = nodePrimaryIp node
179 eaed5f19 Agata Murawska
      port = snd C.daemonsPortsGanetiNoded
180 5b11f8db Iustin Pop
      path_prefix = "https://" ++ node_ip ++ ":" ++ show port
181 5b11f8db Iustin Pop
  in path_prefix ++ "/" ++ rpcCallName call
182 eaed5f19 Agata Murawska
183 eaed5f19 Agata Murawska
-- | Create HTTP request for a given node provided it is online,
184 eaed5f19 Agata Murawska
-- otherwise create empty response.
185 eaed5f19 Agata Murawska
prepareHttpRequest ::  (RpcCall a) => Node -> a
186 599239ad Agata Murawska
                   -> ERpcError HttpClientRequest
187 eaed5f19 Agata Murawska
prepareHttpRequest node call
188 5b11f8db Iustin Pop
  | rpcCallAcceptOffline call || not (nodeOffline node) =
189 5b11f8db Iustin Pop
      Right HttpClientRequest { requestTimeout = rpcCallTimeout call
190 5b11f8db Iustin Pop
                              , requestUrl = prepareUrl node call
191 5b11f8db Iustin Pop
                              , requestPostData = rpcCallData node call
192 5b11f8db Iustin Pop
                              }
193 eaed5f19 Agata Murawska
  | otherwise = Left $ OfflineNodeError node
194 eaed5f19 Agata Murawska
195 9b09c0be Agata Murawska
-- | Parse a result based on the received HTTP response.
196 0ae9ddc4 Agata Murawska
parseHttpResponse :: (Rpc a b) => a -> ERpcError String -> ERpcError b
197 0ae9ddc4 Agata Murawska
parseHttpResponse _ (Left err) = Left err
198 0ae9ddc4 Agata Murawska
parseHttpResponse call (Right res) =
199 a93b711b Agata Murawska
  case J.decode res of
200 a93b711b Agata Murawska
    J.Error val -> Left $ JsonDecodeError val
201 a93b711b Agata Murawska
    J.Ok (True, res'') -> rpcResultFill call res''
202 a93b711b Agata Murawska
    J.Ok (False, jerr) -> case jerr of
203 a93b711b Agata Murawska
       J.JSString msg -> Left $ RpcResultError (J.fromJSString msg)
204 a93b711b Agata Murawska
       _ -> Left . JsonDecodeError $ show (pp_value jerr)
205 9b09c0be Agata Murawska
206 eaed5f19 Agata Murawska
-- | Execute RPC call for a sigle node.
207 599239ad Agata Murawska
executeSingleRpcCall :: (Rpc a b) => Node -> a -> IO (Node, ERpcError b)
208 eaed5f19 Agata Murawska
executeSingleRpcCall node call = do
209 eaed5f19 Agata Murawska
  let request = prepareHttpRequest node call
210 eaed5f19 Agata Murawska
  response <- executeHttpRequest node request
211 a93b711b Agata Murawska
  let result = parseHttpResponse call response
212 eaed5f19 Agata Murawska
  return (node, result)
213 eaed5f19 Agata Murawska
214 eaed5f19 Agata Murawska
-- | Execute RPC call for many nodes in parallel.
215 599239ad Agata Murawska
executeRpcCall :: (Rpc a b) => [Node] -> a -> IO [(Node, ERpcError b)]
216 eaed5f19 Agata Murawska
executeRpcCall nodes call =
217 eaed5f19 Agata Murawska
  sequence $ parMap rwhnf (uncurry executeSingleRpcCall)
218 eaed5f19 Agata Murawska
               (zip nodes $ repeat call)
219 96dad12d Agata Murawska
220 9b09c0be Agata Murawska
-- | Helper function that is used to read dictionaries of values.
221 9b09c0be Agata Murawska
sanitizeDictResults :: [(String, J.Result a)] -> ERpcError [(String, a)]
222 3d3f562b Agata Murawska
sanitizeDictResults =
223 3d3f562b Agata Murawska
  foldr sanitize1 (Right [])
224 3d3f562b Agata Murawska
  where
225 3d3f562b Agata Murawska
    sanitize1 _ (Left e) = Left e
226 3d3f562b Agata Murawska
    sanitize1 (_, J.Error e) _ = Left $ JsonDecodeError e
227 3d3f562b Agata Murawska
    sanitize1 (name, J.Ok v) (Right res) = Right $ (name, v) : res
228 9b09c0be Agata Murawska
229 7328a28c Agata Murawska
-- | Helper function to tranform JSON Result to Either RpcError b.
230 7328a28c Agata Murawska
-- Note: For now we really only use it for b s.t. Rpc c b for some c
231 7328a28c Agata Murawska
fromJResultToRes :: J.Result a -> (a -> b) -> ERpcError b
232 7328a28c Agata Murawska
fromJResultToRes (J.Error v) _ = Left $ JsonDecodeError v
233 7328a28c Agata Murawska
fromJResultToRes (J.Ok v) f = Right $ f v
234 7328a28c Agata Murawska
235 7328a28c Agata Murawska
-- | Helper function transforming JSValue to Rpc result type.
236 7328a28c Agata Murawska
fromJSValueToRes :: (J.JSON a) => J.JSValue -> (a -> b) -> ERpcError b
237 7328a28c Agata Murawska
fromJSValueToRes val = fromJResultToRes (J.readJSON val)
238 7328a28c Agata Murawska
239 96dad12d Agata Murawska
-- * RPC calls and results
240 96dad12d Agata Murawska
241 de2a5704 Iustin Pop
-- ** Instance info
242 de2a5704 Iustin Pop
243 5188fdb7 Agata Murawska
-- | InstanceInfo
244 5188fdb7 Agata Murawska
--   Returns information about a single instance.
245 5188fdb7 Agata Murawska
246 5188fdb7 Agata Murawska
$(buildObject "RpcCallInstanceInfo" "rpcCallInstInfo"
247 5188fdb7 Agata Murawska
  [ simpleField "instance" [t| String |]
248 5188fdb7 Agata Murawska
  , simpleField "hname" [t| Hypervisor |]
249 5188fdb7 Agata Murawska
  ])
250 96dad12d Agata Murawska
251 5b11f8db Iustin Pop
$(buildObject "InstanceInfo" "instInfo"
252 9b09c0be Agata Murawska
  [ simpleField "memory" [t| Int|]
253 9b09c0be Agata Murawska
  , simpleField "state"  [t| String |] -- It depends on hypervisor :(
254 96dad12d Agata Murawska
  , simpleField "vcpus"  [t| Int |]
255 96dad12d Agata Murawska
  , simpleField "time"   [t| Int |]
256 96dad12d Agata Murawska
  ])
257 96dad12d Agata Murawska
258 5188fdb7 Agata Murawska
-- This is optional here because the result may be empty if instance is
259 5188fdb7 Agata Murawska
-- not on a node - and this is not considered an error.
260 5188fdb7 Agata Murawska
$(buildObject "RpcResultInstanceInfo" "rpcResInstInfo"
261 5188fdb7 Agata Murawska
  [ optionalField $ simpleField "inst_info" [t| InstanceInfo |]])
262 5188fdb7 Agata Murawska
263 5188fdb7 Agata Murawska
instance RpcCall RpcCallInstanceInfo where
264 274366e5 Agata Murawska
  rpcCallName _          = "instance_info"
265 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
266 5188fdb7 Agata Murawska
  rpcCallAcceptOffline _ = False
267 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode
268 5188fdb7 Agata Murawska
    ( rpcCallInstInfoInstance call
269 5188fdb7 Agata Murawska
    , rpcCallInstInfoHname call
270 5188fdb7 Agata Murawska
    )
271 5188fdb7 Agata Murawska
272 5188fdb7 Agata Murawska
instance Rpc RpcCallInstanceInfo RpcResultInstanceInfo where
273 5188fdb7 Agata Murawska
  rpcResultFill _ res =
274 a93b711b Agata Murawska
    case res of
275 5188fdb7 Agata Murawska
      J.JSObject res' ->
276 5188fdb7 Agata Murawska
        case J.fromJSObject res' of
277 5188fdb7 Agata Murawska
          [] -> Right $ RpcResultInstanceInfo Nothing
278 7328a28c Agata Murawska
          _ -> fromJSValueToRes res (RpcResultInstanceInfo . Just)
279 5188fdb7 Agata Murawska
      _ -> Left $ JsonDecodeError
280 70c2362e Agata Murawska
           ("Expected JSObject, got " ++ show (pp_value res))
281 5188fdb7 Agata Murawska
282 de2a5704 Iustin Pop
-- ** AllInstancesInfo
283 de2a5704 Iustin Pop
284 5188fdb7 Agata Murawska
-- | AllInstancesInfo
285 5188fdb7 Agata Murawska
--   Returns information about all running instances on the given nodes
286 5188fdb7 Agata Murawska
$(buildObject "RpcCallAllInstancesInfo" "rpcCallAllInstInfo"
287 5188fdb7 Agata Murawska
  [ simpleField "hypervisors" [t| [Hypervisor] |] ])
288 5188fdb7 Agata Murawska
289 5b11f8db Iustin Pop
$(buildObject "RpcResultAllInstancesInfo" "rpcResAllInstInfo"
290 9b09c0be Agata Murawska
  [ simpleField "instances" [t| [(String, InstanceInfo)] |] ])
291 96dad12d Agata Murawska
292 96dad12d Agata Murawska
instance RpcCall RpcCallAllInstancesInfo where
293 274366e5 Agata Murawska
  rpcCallName _          = "all_instances_info"
294 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
295 96dad12d Agata Murawska
  rpcCallAcceptOffline _ = False
296 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode [rpcCallAllInstInfoHypervisors call]
297 9b09c0be Agata Murawska
298 47163f0f Agata Murawska
instance Rpc RpcCallAllInstancesInfo RpcResultAllInstancesInfo where
299 9b09c0be Agata Murawska
  -- FIXME: Is there a simpler way to do it?
300 47163f0f Agata Murawska
  rpcResultFill _ res =
301 a93b711b Agata Murawska
    case res of
302 a93b711b Agata Murawska
      J.JSObject res' ->
303 9b09c0be Agata Murawska
        let res'' = map (second J.readJSON) (J.fromJSObject res')
304 a93b711b Agata Murawska
                        :: [(String, J.Result InstanceInfo)] in
305 9b09c0be Agata Murawska
        case sanitizeDictResults res'' of
306 9b09c0be Agata Murawska
          Left err -> Left err
307 9b09c0be Agata Murawska
          Right insts -> Right $ RpcResultAllInstancesInfo insts
308 9b09c0be Agata Murawska
      _ -> Left $ JsonDecodeError
309 70c2362e Agata Murawska
           ("Expected JSObject, got " ++ show (pp_value res))
310 96dad12d Agata Murawska
311 de2a5704 Iustin Pop
-- ** InstanceList
312 de2a5704 Iustin Pop
313 c1c5aab1 Agata Murawska
-- | InstanceList
314 c1c5aab1 Agata Murawska
-- Returns the list of running instances on the given nodes.
315 5b11f8db Iustin Pop
$(buildObject "RpcCallInstanceList" "rpcCallInstList"
316 c1c5aab1 Agata Murawska
  [ simpleField "hypervisors" [t| [Hypervisor] |] ])
317 c1c5aab1 Agata Murawska
318 5b11f8db Iustin Pop
$(buildObject "RpcResultInstanceList" "rpcResInstList"
319 9b09c0be Agata Murawska
  [ simpleField "instances" [t| [String] |] ])
320 c1c5aab1 Agata Murawska
321 c1c5aab1 Agata Murawska
instance RpcCall RpcCallInstanceList where
322 274366e5 Agata Murawska
  rpcCallName _          = "instance_list"
323 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
324 c1c5aab1 Agata Murawska
  rpcCallAcceptOffline _ = False
325 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode [rpcCallInstListHypervisors call]
326 c1c5aab1 Agata Murawska
327 47163f0f Agata Murawska
instance Rpc RpcCallInstanceList RpcResultInstanceList where
328 7328a28c Agata Murawska
  rpcResultFill _ res = fromJSValueToRes res RpcResultInstanceList
329 c1c5aab1 Agata Murawska
330 de2a5704 Iustin Pop
-- ** NodeInfo
331 de2a5704 Iustin Pop
332 dc623a95 Agata Murawska
-- | NodeInfo
333 dc623a95 Agata Murawska
-- Return node information.
334 5b11f8db Iustin Pop
$(buildObject "RpcCallNodeInfo" "rpcCallNodeInfo"
335 9b09c0be Agata Murawska
  [ simpleField "volume_groups" [t| [String] |]
336 9b09c0be Agata Murawska
  , simpleField "hypervisors" [t| [Hypervisor] |]
337 319322a7 Bernardo Dal Seno
  , simpleField "exclusive_storage" [t| Map.Map String Bool |]
338 dc623a95 Agata Murawska
  ])
339 dc623a95 Agata Murawska
340 5b11f8db Iustin Pop
$(buildObject "VgInfo" "vgInfo"
341 dc623a95 Agata Murawska
  [ simpleField "name" [t| String |]
342 9b09c0be Agata Murawska
  , optionalField $ simpleField "vg_free" [t| Int |]
343 9b09c0be Agata Murawska
  , optionalField $ simpleField "vg_size" [t| Int |]
344 dc623a95 Agata Murawska
  ])
345 dc623a95 Agata Murawska
346 dc623a95 Agata Murawska
-- | We only provide common fields as described in hv_base.py.
347 5b11f8db Iustin Pop
$(buildObject "HvInfo" "hvInfo"
348 dc623a95 Agata Murawska
  [ simpleField "memory_total" [t| Int |]
349 dc623a95 Agata Murawska
  , simpleField "memory_free" [t| Int |]
350 dc623a95 Agata Murawska
  , simpleField "memory_dom0" [t| Int |]
351 dc623a95 Agata Murawska
  , simpleField "cpu_total" [t| Int |]
352 dc623a95 Agata Murawska
  , simpleField "cpu_nodes" [t| Int |]
353 dc623a95 Agata Murawska
  , simpleField "cpu_sockets" [t| Int |]
354 dc623a95 Agata Murawska
  ])
355 dc623a95 Agata Murawska
356 5b11f8db Iustin Pop
$(buildObject "RpcResultNodeInfo" "rpcResNodeInfo"
357 dc623a95 Agata Murawska
  [ simpleField "boot_id" [t| String |]
358 dc623a95 Agata Murawska
  , simpleField "vg_info" [t| [VgInfo] |]
359 dc623a95 Agata Murawska
  , simpleField "hv_info" [t| [HvInfo] |]
360 dc623a95 Agata Murawska
  ])
361 dc623a95 Agata Murawska
362 dc623a95 Agata Murawska
instance RpcCall RpcCallNodeInfo where
363 274366e5 Agata Murawska
  rpcCallName _          = "node_info"
364 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
365 dc623a95 Agata Murawska
  rpcCallAcceptOffline _ = False
366 319322a7 Bernardo Dal Seno
  rpcCallData n call     = J.encode
367 274366e5 Agata Murawska
    ( rpcCallNodeInfoVolumeGroups call
368 274366e5 Agata Murawska
    , rpcCallNodeInfoHypervisors call
369 319322a7 Bernardo Dal Seno
    , fromMaybe (error $ "Programmer error: missing parameter for node named "
370 319322a7 Bernardo Dal Seno
                         ++ nodeName n)
371 319322a7 Bernardo Dal Seno
                $ Map.lookup (nodeName n) (rpcCallNodeInfoExclusiveStorage call)
372 274366e5 Agata Murawska
    )
373 9b09c0be Agata Murawska
374 47163f0f Agata Murawska
instance Rpc RpcCallNodeInfo RpcResultNodeInfo where
375 47163f0f Agata Murawska
  rpcResultFill _ res =
376 7328a28c Agata Murawska
    fromJSValueToRes res (\(b, vg, hv) -> RpcResultNodeInfo b vg hv)
377 dc623a95 Agata Murawska
378 de2a5704 Iustin Pop
-- ** Version
379 de2a5704 Iustin Pop
380 8779d21a Agata Murawska
-- | Version
381 8779d21a Agata Murawska
-- Query node version.
382 8779d21a Agata Murawska
-- Note: We can't use THH as it does not know what to do with empty dict
383 8779d21a Agata Murawska
data RpcCallVersion = RpcCallVersion {}
384 139c0683 Iustin Pop
  deriving (Show, Eq)
385 8779d21a Agata Murawska
386 8779d21a Agata Murawska
instance J.JSON RpcCallVersion where
387 8779d21a Agata Murawska
  showJSON _ = J.JSNull
388 8779d21a Agata Murawska
  readJSON J.JSNull = return RpcCallVersion
389 8779d21a Agata Murawska
  readJSON _ = fail "Unable to read RpcCallVersion"
390 8779d21a Agata Murawska
391 8779d21a Agata Murawska
$(buildObject "RpcResultVersion" "rpcResultVersion"
392 8779d21a Agata Murawska
  [ simpleField "version" [t| Int |]
393 8779d21a Agata Murawska
  ])
394 8779d21a Agata Murawska
395 8779d21a Agata Murawska
instance RpcCall RpcCallVersion where
396 274366e5 Agata Murawska
  rpcCallName _          = "version"
397 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
398 8779d21a Agata Murawska
  rpcCallAcceptOffline _ = True
399 ff8f0049 Iustin Pop
  rpcCallData _          = J.encode
400 8779d21a Agata Murawska
401 47163f0f Agata Murawska
instance Rpc RpcCallVersion RpcResultVersion where
402 7328a28c Agata Murawska
  rpcResultFill _ res = fromJSValueToRes res RpcResultVersion
403 8779d21a Agata Murawska
404 de2a5704 Iustin Pop
-- ** StorageList
405 de2a5704 Iustin Pop
406 47163f0f Agata Murawska
-- | StorageList
407 47163f0f Agata Murawska
408 47163f0f Agata Murawska
-- FIXME: This may be moved to Objects
409 47163f0f Agata Murawska
$(declareSADT "StorageField"
410 47163f0f Agata Murawska
  [ ( "SFUsed",        'C.sfUsed)
411 47163f0f Agata Murawska
  , ( "SFName",        'C.sfName)
412 47163f0f Agata Murawska
  , ( "SFAllocatable", 'C.sfAllocatable)
413 47163f0f Agata Murawska
  , ( "SFFree",        'C.sfFree)
414 47163f0f Agata Murawska
  , ( "SFSize",        'C.sfSize)
415 47163f0f Agata Murawska
  ])
416 47163f0f Agata Murawska
$(makeJSONInstance ''StorageField)
417 47163f0f Agata Murawska
418 47163f0f Agata Murawska
$(buildObject "RpcCallStorageList" "rpcCallStorageList"
419 47163f0f Agata Murawska
  [ simpleField "su_name" [t| StorageType |]
420 47163f0f Agata Murawska
  , simpleField "su_args" [t| [String] |]
421 47163f0f Agata Murawska
  , simpleField "name"    [t| String |]
422 47163f0f Agata Murawska
  , simpleField "fields"  [t| [StorageField] |]
423 47163f0f Agata Murawska
  ])
424 47163f0f Agata Murawska
425 47163f0f Agata Murawska
-- FIXME: The resulting JSValues should have types appropriate for their
426 47163f0f Agata Murawska
-- StorageField value: Used -> Bool, Name -> String etc
427 47163f0f Agata Murawska
$(buildObject "RpcResultStorageList" "rpcResStorageList"
428 47163f0f Agata Murawska
  [ simpleField "storage" [t| [[(StorageField, J.JSValue)]] |] ])
429 47163f0f Agata Murawska
430 47163f0f Agata Murawska
instance RpcCall RpcCallStorageList where
431 274366e5 Agata Murawska
  rpcCallName _          = "storage_list"
432 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Normal
433 47163f0f Agata Murawska
  rpcCallAcceptOffline _ = False
434 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode
435 47163f0f Agata Murawska
    ( rpcCallStorageListSuName call
436 47163f0f Agata Murawska
    , rpcCallStorageListSuArgs call
437 47163f0f Agata Murawska
    , rpcCallStorageListName call
438 47163f0f Agata Murawska
    , rpcCallStorageListFields call
439 47163f0f Agata Murawska
    )
440 47163f0f Agata Murawska
441 47163f0f Agata Murawska
instance Rpc RpcCallStorageList RpcResultStorageList where
442 47163f0f Agata Murawska
  rpcResultFill call res =
443 47163f0f Agata Murawska
    let sfields = rpcCallStorageListFields call in
444 7328a28c Agata Murawska
    fromJSValueToRes res (RpcResultStorageList . map (zip sfields))
445 de2a5704 Iustin Pop
446 de2a5704 Iustin Pop
-- ** TestDelay
447 de2a5704 Iustin Pop
448 de2a5704 Iustin Pop
449 de2a5704 Iustin Pop
-- | Call definition for test delay.
450 de2a5704 Iustin Pop
$(buildObject "RpcCallTestDelay" "rpcCallTestDelay"
451 de2a5704 Iustin Pop
  [ simpleField "duration" [t| Double |]
452 de2a5704 Iustin Pop
  ])
453 de2a5704 Iustin Pop
454 de2a5704 Iustin Pop
-- | Result definition for test delay.
455 de2a5704 Iustin Pop
data RpcResultTestDelay = RpcResultTestDelay
456 de2a5704 Iustin Pop
                          deriving Show
457 de2a5704 Iustin Pop
458 de2a5704 Iustin Pop
-- | Custom JSON instance for null result.
459 de2a5704 Iustin Pop
instance J.JSON RpcResultTestDelay where
460 de2a5704 Iustin Pop
  showJSON _        = J.JSNull
461 de2a5704 Iustin Pop
  readJSON J.JSNull = return RpcResultTestDelay
462 de2a5704 Iustin Pop
  readJSON _        = fail "Unable to read RpcResultTestDelay"
463 de2a5704 Iustin Pop
464 de2a5704 Iustin Pop
instance RpcCall RpcCallTestDelay where
465 de2a5704 Iustin Pop
  rpcCallName _          = "test_delay"
466 de2a5704 Iustin Pop
  rpcCallTimeout         = ceiling . (+ 5) . rpcCallTestDelayDuration
467 de2a5704 Iustin Pop
  rpcCallAcceptOffline _ = False
468 de2a5704 Iustin Pop
  rpcCallData _ call     = J.encode [rpcCallTestDelayDuration call]
469 de2a5704 Iustin Pop
470 de2a5704 Iustin Pop
instance Rpc RpcCallTestDelay RpcResultTestDelay where
471 de2a5704 Iustin Pop
  rpcResultFill _ res = fromJSValueToRes res id