Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / Rpc.hs @ 29a30533

History | View | Annotate | Download (15.4 kB)

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