Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Rpc.hs @ b6e31235

History | View | Annotate | Download (15.7 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 a246ce76 Michele Tartara
  , logRpcErrors
37 d4709cce Agata Murawska
38 d4709cce Agata Murawska
  , rpcCallName
39 d4709cce Agata Murawska
  , rpcCallTimeout
40 d4709cce Agata Murawska
  , rpcCallData
41 d4709cce Agata Murawska
  , rpcCallAcceptOffline
42 d4709cce Agata Murawska
43 d4709cce Agata Murawska
  , rpcResultFill
44 96dad12d Agata Murawska
45 96dad12d Agata Murawska
  , InstanceInfo(..)
46 5188fdb7 Agata Murawska
  , RpcCallInstanceInfo(..)
47 5188fdb7 Agata Murawska
  , RpcResultInstanceInfo(..)
48 5188fdb7 Agata Murawska
49 96dad12d Agata Murawska
  , RpcCallAllInstancesInfo(..)
50 96dad12d Agata Murawska
  , RpcResultAllInstancesInfo(..)
51 96dad12d Agata Murawska
52 c1c5aab1 Agata Murawska
  , RpcCallInstanceList(..)
53 c1c5aab1 Agata Murawska
  , RpcResultInstanceList(..)
54 c1c5aab1 Agata Murawska
55 dc623a95 Agata Murawska
  , HvInfo(..)
56 32389d91 Helga Velroyen
  , StorageInfo(..)
57 dc623a95 Agata Murawska
  , RpcCallNodeInfo(..)
58 dc623a95 Agata Murawska
  , RpcResultNodeInfo(..)
59 dc623a95 Agata Murawska
60 8779d21a Agata Murawska
  , RpcCallVersion(..)
61 8779d21a Agata Murawska
  , RpcResultVersion(..)
62 8779d21a Agata Murawska
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 842515dd Iustin Pop
  , RpcCallExportList(..)
70 842515dd Iustin Pop
  , RpcResultExportList(..)
71 d4709cce Agata Murawska
  ) where
72 d4709cce Agata Murawska
73 9b09c0be Agata Murawska
import Control.Arrow (second)
74 319322a7 Bernardo Dal Seno
import qualified Data.Map as Map
75 319322a7 Bernardo Dal Seno
import Data.Maybe (fromMaybe)
76 d4709cce Agata Murawska
import qualified Text.JSON as J
77 9b09c0be Agata Murawska
import Text.JSON.Pretty (pp_value)
78 d4709cce Agata Murawska
79 eaed5f19 Agata Murawska
import Network.Curl
80 7766de33 Agata Murawska
import qualified Ganeti.Path as P
81 eaed5f19 Agata Murawska
82 8920fa09 Iustin Pop
import Ganeti.BasicTypes
83 eaed5f19 Agata Murawska
import qualified Ganeti.Constants as C
84 a246ce76 Michele Tartara
import Ganeti.Logging
85 d4709cce Agata Murawska
import Ganeti.Objects
86 96dad12d Agata Murawska
import Ganeti.THH
87 22381768 Iustin Pop
import Ganeti.Types
88 8920fa09 Iustin Pop
import Ganeti.Curl.Multi
89 8920fa09 Iustin Pop
import Ganeti.Utils
90 eaed5f19 Agata Murawska
91 de2a5704 Iustin Pop
-- * Base RPC functionality and types
92 de2a5704 Iustin Pop
93 eaed5f19 Agata Murawska
-- | The curl options used for RPC.
94 eaed5f19 Agata Murawska
curlOpts :: [CurlOption]
95 eaed5f19 Agata Murawska
curlOpts = [ CurlFollowLocation False
96 eaed5f19 Agata Murawska
           , CurlSSLVerifyHost 0
97 eaed5f19 Agata Murawska
           , CurlSSLVerifyPeer True
98 eaed5f19 Agata Murawska
           , CurlSSLCertType "PEM"
99 eaed5f19 Agata Murawska
           , CurlSSLKeyType "PEM"
100 eaed5f19 Agata Murawska
           , CurlConnectTimeout (fromIntegral C.rpcConnectTimeout)
101 eaed5f19 Agata Murawska
           ]
102 d4709cce Agata Murawska
103 d4709cce Agata Murawska
-- | Data type for RPC error reporting.
104 d4709cce Agata Murawska
data RpcError
105 9c0a27d0 Iustin Pop
  = CurlLayerError String
106 d4709cce Agata Murawska
  | JsonDecodeError String
107 6fddde87 Agata Murawska
  | RpcResultError String
108 9c0a27d0 Iustin Pop
  | OfflineNodeError
109 60443f61 Agata Murawska
  deriving (Show, Eq)
110 d4709cce Agata Murawska
111 60443f61 Agata Murawska
-- | Provide explanation to RPC errors.
112 60443f61 Agata Murawska
explainRpcError :: RpcError -> String
113 9c0a27d0 Iustin Pop
explainRpcError (CurlLayerError code) =
114 9c0a27d0 Iustin Pop
    "Curl error:" ++ code
115 60443f61 Agata Murawska
explainRpcError (JsonDecodeError msg) =
116 6fddde87 Agata Murawska
    "Error while decoding JSON from HTTP response: " ++ msg
117 60443f61 Agata Murawska
explainRpcError (RpcResultError msg) =
118 6fddde87 Agata Murawska
    "Error reponse received from RPC server: " ++ msg
119 9c0a27d0 Iustin Pop
explainRpcError OfflineNodeError =
120 9c0a27d0 Iustin Pop
    "Node is marked offline"
121 d4709cce Agata Murawska
122 599239ad Agata Murawska
type ERpcError = Either RpcError
123 599239ad Agata Murawska
124 d4709cce Agata Murawska
-- | A generic class for RPC calls.
125 d4709cce Agata Murawska
class (J.JSON a) => RpcCall a where
126 d4709cce Agata Murawska
  -- | Give the (Python) name of the procedure.
127 d4709cce Agata Murawska
  rpcCallName :: a -> String
128 d4709cce Agata Murawska
  -- | Calculate the timeout value for the call execution.
129 d4709cce Agata Murawska
  rpcCallTimeout :: a -> Int
130 d4709cce Agata Murawska
  -- | Prepare arguments of the call to be send as POST.
131 d4709cce Agata Murawska
  rpcCallData :: Node -> a -> String
132 d4709cce Agata Murawska
  -- | Whether we accept offline nodes when making a call.
133 d4709cce Agata Murawska
  rpcCallAcceptOffline :: a -> Bool
134 d4709cce Agata Murawska
135 d4709cce Agata Murawska
-- | Generic class that ensures matching RPC call with its respective
136 d4709cce Agata Murawska
-- result.
137 47163f0f Agata Murawska
class (RpcCall a, J.JSON b) => Rpc a b  | a -> b, b -> a where
138 47163f0f Agata Murawska
  -- | Create a result based on the received HTTP response.
139 a93b711b Agata Murawska
  rpcResultFill :: a -> J.JSValue -> ERpcError b
140 eaed5f19 Agata Murawska
141 eaed5f19 Agata Murawska
-- | Http Request definition.
142 eaed5f19 Agata Murawska
data HttpClientRequest = HttpClientRequest
143 85f6a869 Iustin Pop
  { requestUrl  :: String       -- ^ The actual URL for the node endpoint
144 85f6a869 Iustin Pop
  , requestData :: String       -- ^ The arguments for the call
145 85f6a869 Iustin Pop
  , requestOpts :: [CurlOption] -- ^ The various curl options
146 eaed5f19 Agata Murawska
  }
147 eaed5f19 Agata Murawska
148 b5c3a4f2 Guido Trotter
-- | Check if a string represented address is IPv6
149 b5c3a4f2 Guido Trotter
isIpV6 :: String -> Bool
150 289e7fcc Klaus Aehlig
isIpV6 = (':' `elem`)
151 b5c3a4f2 Guido Trotter
152 eaed5f19 Agata Murawska
-- | Prepare url for the HTTP request.
153 eaed5f19 Agata Murawska
prepareUrl :: (RpcCall a) => Node -> a -> String
154 eaed5f19 Agata Murawska
prepareUrl node call =
155 eaed5f19 Agata Murawska
  let node_ip = nodePrimaryIp node
156 b5c3a4f2 Guido Trotter
      node_address = if isIpV6 node_ip
157 b5c3a4f2 Guido Trotter
                     then "[" ++ node_ip ++ "]"
158 b5c3a4f2 Guido Trotter
                     else node_ip
159 6dc0cb59 Jose A. Lopes
      port = C.defaultNodedPort
160 b5c3a4f2 Guido Trotter
      path_prefix = "https://" ++ node_address ++ ":" ++ show port
161 5b11f8db Iustin Pop
  in path_prefix ++ "/" ++ rpcCallName call
162 eaed5f19 Agata Murawska
163 eaed5f19 Agata Murawska
-- | Create HTTP request for a given node provided it is online,
164 eaed5f19 Agata Murawska
-- otherwise create empty response.
165 85f6a869 Iustin Pop
prepareHttpRequest :: (RpcCall a) => [CurlOption] -> Node -> a
166 599239ad Agata Murawska
                   -> ERpcError HttpClientRequest
167 85f6a869 Iustin Pop
prepareHttpRequest opts node call
168 5b11f8db Iustin Pop
  | rpcCallAcceptOffline call || not (nodeOffline node) =
169 85f6a869 Iustin Pop
      Right HttpClientRequest { requestUrl  = prepareUrl node call
170 85f6a869 Iustin Pop
                              , requestData = rpcCallData node call
171 85f6a869 Iustin Pop
                              , requestOpts = opts ++ curlOpts
172 5b11f8db Iustin Pop
                              }
173 9c0a27d0 Iustin Pop
  | otherwise = Left OfflineNodeError
174 eaed5f19 Agata Murawska
175 8920fa09 Iustin Pop
-- | Parse an HTTP reply.
176 8920fa09 Iustin Pop
parseHttpReply :: (Rpc a b) =>
177 8920fa09 Iustin Pop
                  a -> ERpcError (CurlCode, String) -> ERpcError b
178 8920fa09 Iustin Pop
parseHttpReply _ (Left e) = Left e
179 8920fa09 Iustin Pop
parseHttpReply call (Right (CurlOK, body)) = parseHttpResponse call body
180 8920fa09 Iustin Pop
parseHttpReply _ (Right (code, err)) =
181 8920fa09 Iustin Pop
  Left . CurlLayerError $ "code: " ++ show code ++ ", explanation: " ++ err
182 8920fa09 Iustin Pop
183 9b09c0be Agata Murawska
-- | Parse a result based on the received HTTP response.
184 8920fa09 Iustin Pop
parseHttpResponse :: (Rpc a b) => a -> String -> ERpcError b
185 8920fa09 Iustin Pop
parseHttpResponse call res =
186 a93b711b Agata Murawska
  case J.decode res of
187 a93b711b Agata Murawska
    J.Error val -> Left $ JsonDecodeError val
188 a93b711b Agata Murawska
    J.Ok (True, res'') -> rpcResultFill call res''
189 a93b711b Agata Murawska
    J.Ok (False, jerr) -> case jerr of
190 a93b711b Agata Murawska
       J.JSString msg -> Left $ RpcResultError (J.fromJSString msg)
191 a93b711b Agata Murawska
       _ -> Left . JsonDecodeError $ show (pp_value jerr)
192 9b09c0be Agata Murawska
193 a246ce76 Michele Tartara
-- | Scan the list of results produced by executeRpcCall and log all the RPC
194 a246ce76 Michele Tartara
-- errors.
195 a246ce76 Michele Tartara
logRpcErrors :: [(a, ERpcError b)] -> IO ()
196 a246ce76 Michele Tartara
logRpcErrors allElems =
197 a246ce76 Michele Tartara
  let logOneRpcErr (_, Right _) = return ()
198 a246ce76 Michele Tartara
      logOneRpcErr (_, Left err) =
199 a246ce76 Michele Tartara
        logError $ "Error in the RPC HTTP reply: " ++ show err
200 a246ce76 Michele Tartara
  in mapM_ logOneRpcErr allElems
201 a246ce76 Michele Tartara
202 eaed5f19 Agata Murawska
-- | Execute RPC call for many nodes in parallel.
203 599239ad Agata Murawska
executeRpcCall :: (Rpc a b) => [Node] -> a -> IO [(Node, ERpcError b)]
204 85f6a869 Iustin Pop
executeRpcCall nodes call = do
205 85f6a869 Iustin Pop
  cert_file <- P.nodedCertFile
206 85f6a869 Iustin Pop
  let opts = [ CurlTimeout (fromIntegral $ rpcCallTimeout call)
207 85f6a869 Iustin Pop
             , CurlSSLCert cert_file
208 85f6a869 Iustin Pop
             , CurlSSLKey cert_file
209 85f6a869 Iustin Pop
             , CurlCAInfo cert_file
210 85f6a869 Iustin Pop
             ]
211 8920fa09 Iustin Pop
      opts_urls = map (\n ->
212 8920fa09 Iustin Pop
                         case prepareHttpRequest opts n call of
213 8920fa09 Iustin Pop
                           Left v -> Left v
214 8920fa09 Iustin Pop
                           Right request ->
215 8920fa09 Iustin Pop
                             Right (CurlPostFields [requestData request]:
216 8920fa09 Iustin Pop
                                    requestOpts request,
217 8920fa09 Iustin Pop
                                    requestUrl request)
218 8920fa09 Iustin Pop
                      ) nodes
219 8920fa09 Iustin Pop
  -- split the opts_urls list; we don't want to pass the
220 8920fa09 Iustin Pop
  -- failed-already nodes to Curl
221 8920fa09 Iustin Pop
  let (lefts, rights, trail) = splitEithers opts_urls
222 8920fa09 Iustin Pop
  results <- execMultiCall rights
223 8920fa09 Iustin Pop
  results' <- case recombineEithers lefts results trail of
224 8920fa09 Iustin Pop
                Bad msg -> error msg
225 8920fa09 Iustin Pop
                Ok r -> return r
226 8920fa09 Iustin Pop
  -- now parse the replies
227 8920fa09 Iustin Pop
  let results'' = map (parseHttpReply call) results'
228 c393abbf Michele Tartara
      pairedList = zip nodes results''
229 c393abbf Michele Tartara
  logRpcErrors pairedList
230 c393abbf Michele Tartara
  return pairedList
231 96dad12d Agata Murawska
232 9b09c0be Agata Murawska
-- | Helper function that is used to read dictionaries of values.
233 9b09c0be Agata Murawska
sanitizeDictResults :: [(String, J.Result a)] -> ERpcError [(String, a)]
234 3d3f562b Agata Murawska
sanitizeDictResults =
235 3d3f562b Agata Murawska
  foldr sanitize1 (Right [])
236 3d3f562b Agata Murawska
  where
237 3d3f562b Agata Murawska
    sanitize1 _ (Left e) = Left e
238 3d3f562b Agata Murawska
    sanitize1 (_, J.Error e) _ = Left $ JsonDecodeError e
239 3d3f562b Agata Murawska
    sanitize1 (name, J.Ok v) (Right res) = Right $ (name, v) : res
240 9b09c0be Agata Murawska
241 7328a28c Agata Murawska
-- | Helper function to tranform JSON Result to Either RpcError b.
242 7328a28c Agata Murawska
-- Note: For now we really only use it for b s.t. Rpc c b for some c
243 7328a28c Agata Murawska
fromJResultToRes :: J.Result a -> (a -> b) -> ERpcError b
244 7328a28c Agata Murawska
fromJResultToRes (J.Error v) _ = Left $ JsonDecodeError v
245 7328a28c Agata Murawska
fromJResultToRes (J.Ok v) f = Right $ f v
246 7328a28c Agata Murawska
247 7328a28c Agata Murawska
-- | Helper function transforming JSValue to Rpc result type.
248 7328a28c Agata Murawska
fromJSValueToRes :: (J.JSON a) => J.JSValue -> (a -> b) -> ERpcError b
249 7328a28c Agata Murawska
fromJSValueToRes val = fromJResultToRes (J.readJSON val)
250 7328a28c Agata Murawska
251 96dad12d Agata Murawska
-- * RPC calls and results
252 96dad12d Agata Murawska
253 de2a5704 Iustin Pop
-- ** Instance info
254 de2a5704 Iustin Pop
255 5188fdb7 Agata Murawska
-- | InstanceInfo
256 5188fdb7 Agata Murawska
--   Returns information about a single instance.
257 5188fdb7 Agata Murawska
258 5188fdb7 Agata Murawska
$(buildObject "RpcCallInstanceInfo" "rpcCallInstInfo"
259 5188fdb7 Agata Murawska
  [ simpleField "instance" [t| String |]
260 5188fdb7 Agata Murawska
  , simpleField "hname" [t| Hypervisor |]
261 5188fdb7 Agata Murawska
  ])
262 96dad12d Agata Murawska
263 5b11f8db Iustin Pop
$(buildObject "InstanceInfo" "instInfo"
264 9b09c0be Agata Murawska
  [ simpleField "memory" [t| Int|]
265 9b09c0be Agata Murawska
  , simpleField "state"  [t| String |] -- It depends on hypervisor :(
266 96dad12d Agata Murawska
  , simpleField "vcpus"  [t| Int |]
267 96dad12d Agata Murawska
  , simpleField "time"   [t| Int |]
268 96dad12d Agata Murawska
  ])
269 96dad12d Agata Murawska
270 5188fdb7 Agata Murawska
-- This is optional here because the result may be empty if instance is
271 5188fdb7 Agata Murawska
-- not on a node - and this is not considered an error.
272 5188fdb7 Agata Murawska
$(buildObject "RpcResultInstanceInfo" "rpcResInstInfo"
273 5188fdb7 Agata Murawska
  [ optionalField $ simpleField "inst_info" [t| InstanceInfo |]])
274 5188fdb7 Agata Murawska
275 5188fdb7 Agata Murawska
instance RpcCall RpcCallInstanceInfo where
276 274366e5 Agata Murawska
  rpcCallName _          = "instance_info"
277 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
278 5188fdb7 Agata Murawska
  rpcCallAcceptOffline _ = False
279 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode
280 5188fdb7 Agata Murawska
    ( rpcCallInstInfoInstance call
281 5188fdb7 Agata Murawska
    , rpcCallInstInfoHname call
282 5188fdb7 Agata Murawska
    )
283 5188fdb7 Agata Murawska
284 5188fdb7 Agata Murawska
instance Rpc RpcCallInstanceInfo RpcResultInstanceInfo where
285 5188fdb7 Agata Murawska
  rpcResultFill _ res =
286 a93b711b Agata Murawska
    case res of
287 5188fdb7 Agata Murawska
      J.JSObject res' ->
288 5188fdb7 Agata Murawska
        case J.fromJSObject res' of
289 5188fdb7 Agata Murawska
          [] -> Right $ RpcResultInstanceInfo Nothing
290 7328a28c Agata Murawska
          _ -> fromJSValueToRes res (RpcResultInstanceInfo . Just)
291 5188fdb7 Agata Murawska
      _ -> Left $ JsonDecodeError
292 70c2362e Agata Murawska
           ("Expected JSObject, got " ++ show (pp_value res))
293 5188fdb7 Agata Murawska
294 de2a5704 Iustin Pop
-- ** AllInstancesInfo
295 de2a5704 Iustin Pop
296 5188fdb7 Agata Murawska
-- | AllInstancesInfo
297 5188fdb7 Agata Murawska
--   Returns information about all running instances on the given nodes
298 5188fdb7 Agata Murawska
$(buildObject "RpcCallAllInstancesInfo" "rpcCallAllInstInfo"
299 5188fdb7 Agata Murawska
  [ simpleField "hypervisors" [t| [Hypervisor] |] ])
300 5188fdb7 Agata Murawska
301 5b11f8db Iustin Pop
$(buildObject "RpcResultAllInstancesInfo" "rpcResAllInstInfo"
302 9b09c0be Agata Murawska
  [ simpleField "instances" [t| [(String, InstanceInfo)] |] ])
303 96dad12d Agata Murawska
304 96dad12d Agata Murawska
instance RpcCall RpcCallAllInstancesInfo where
305 274366e5 Agata Murawska
  rpcCallName _          = "all_instances_info"
306 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
307 96dad12d Agata Murawska
  rpcCallAcceptOffline _ = False
308 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode [rpcCallAllInstInfoHypervisors call]
309 9b09c0be Agata Murawska
310 47163f0f Agata Murawska
instance Rpc RpcCallAllInstancesInfo RpcResultAllInstancesInfo where
311 9b09c0be Agata Murawska
  -- FIXME: Is there a simpler way to do it?
312 47163f0f Agata Murawska
  rpcResultFill _ res =
313 a93b711b Agata Murawska
    case res of
314 a93b711b Agata Murawska
      J.JSObject res' ->
315 9b09c0be Agata Murawska
        let res'' = map (second J.readJSON) (J.fromJSObject res')
316 a93b711b Agata Murawska
                        :: [(String, J.Result InstanceInfo)] in
317 9b09c0be Agata Murawska
        case sanitizeDictResults res'' of
318 9b09c0be Agata Murawska
          Left err -> Left err
319 9b09c0be Agata Murawska
          Right insts -> Right $ RpcResultAllInstancesInfo insts
320 9b09c0be Agata Murawska
      _ -> Left $ JsonDecodeError
321 70c2362e Agata Murawska
           ("Expected JSObject, got " ++ show (pp_value res))
322 96dad12d Agata Murawska
323 de2a5704 Iustin Pop
-- ** InstanceList
324 de2a5704 Iustin Pop
325 c1c5aab1 Agata Murawska
-- | InstanceList
326 c1c5aab1 Agata Murawska
-- Returns the list of running instances on the given nodes.
327 5b11f8db Iustin Pop
$(buildObject "RpcCallInstanceList" "rpcCallInstList"
328 c1c5aab1 Agata Murawska
  [ simpleField "hypervisors" [t| [Hypervisor] |] ])
329 c1c5aab1 Agata Murawska
330 5b11f8db Iustin Pop
$(buildObject "RpcResultInstanceList" "rpcResInstList"
331 9b09c0be Agata Murawska
  [ simpleField "instances" [t| [String] |] ])
332 c1c5aab1 Agata Murawska
333 c1c5aab1 Agata Murawska
instance RpcCall RpcCallInstanceList where
334 274366e5 Agata Murawska
  rpcCallName _          = "instance_list"
335 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
336 c1c5aab1 Agata Murawska
  rpcCallAcceptOffline _ = False
337 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode [rpcCallInstListHypervisors call]
338 c1c5aab1 Agata Murawska
339 47163f0f Agata Murawska
instance Rpc RpcCallInstanceList RpcResultInstanceList where
340 7328a28c Agata Murawska
  rpcResultFill _ res = fromJSValueToRes res RpcResultInstanceList
341 c1c5aab1 Agata Murawska
342 de2a5704 Iustin Pop
-- ** NodeInfo
343 de2a5704 Iustin Pop
344 dc623a95 Agata Murawska
-- | NodeInfo
345 dc623a95 Agata Murawska
-- Return node information.
346 5b11f8db Iustin Pop
$(buildObject "RpcCallNodeInfo" "rpcCallNodeInfo"
347 212b66c3 Helga Velroyen
  [ simpleField "storage_units" [t| Map.Map String [StorageUnit] |]
348 030ab01a Helga Velroyen
  , simpleField "hypervisors" [t| [ (Hypervisor, HvParams) ] |]
349 dc623a95 Agata Murawska
  ])
350 dc623a95 Agata Murawska
351 32389d91 Helga Velroyen
$(buildObject "StorageInfo" "storageInfo"
352 dc623a95 Agata Murawska
  [ simpleField "name" [t| String |]
353 0f0f6d7d Helga Velroyen
  , simpleField "type" [t| String |]
354 32389d91 Helga Velroyen
  , optionalField $ simpleField "storage_free" [t| Int |]
355 32389d91 Helga Velroyen
  , optionalField $ simpleField "storage_size" [t| Int |]
356 dc623a95 Agata Murawska
  ])
357 dc623a95 Agata Murawska
358 dc623a95 Agata Murawska
-- | We only provide common fields as described in hv_base.py.
359 5b11f8db Iustin Pop
$(buildObject "HvInfo" "hvInfo"
360 dc623a95 Agata Murawska
  [ simpleField "memory_total" [t| Int |]
361 dc623a95 Agata Murawska
  , simpleField "memory_free" [t| Int |]
362 dc623a95 Agata Murawska
  , simpleField "memory_dom0" [t| Int |]
363 dc623a95 Agata Murawska
  , simpleField "cpu_total" [t| Int |]
364 dc623a95 Agata Murawska
  , simpleField "cpu_nodes" [t| Int |]
365 dc623a95 Agata Murawska
  , simpleField "cpu_sockets" [t| Int |]
366 f43c898d Bernardo Dal Seno
  , simpleField "cpu_dom0" [t| Int |]
367 dc623a95 Agata Murawska
  ])
368 dc623a95 Agata Murawska
369 5b11f8db Iustin Pop
$(buildObject "RpcResultNodeInfo" "rpcResNodeInfo"
370 dc623a95 Agata Murawska
  [ simpleField "boot_id" [t| String |]
371 32389d91 Helga Velroyen
  , simpleField "storage_info" [t| [StorageInfo] |]
372 dc623a95 Agata Murawska
  , simpleField "hv_info" [t| [HvInfo] |]
373 dc623a95 Agata Murawska
  ])
374 dc623a95 Agata Murawska
375 dc623a95 Agata Murawska
instance RpcCall RpcCallNodeInfo where
376 274366e5 Agata Murawska
  rpcCallName _          = "node_info"
377 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
378 dc623a95 Agata Murawska
  rpcCallAcceptOffline _ = False
379 319322a7 Bernardo Dal Seno
  rpcCallData n call     = J.encode
380 212b66c3 Helga Velroyen
    ( fromMaybe (error $ "Programmer error: missing parameter for node named "
381 319322a7 Bernardo Dal Seno
                         ++ nodeName n)
382 212b66c3 Helga Velroyen
          $ Map.lookup (nodeUuid n) (rpcCallNodeInfoStorageUnits call)
383 212b66c3 Helga Velroyen
    , rpcCallNodeInfoHypervisors call
384 274366e5 Agata Murawska
    )
385 9b09c0be Agata Murawska
386 47163f0f Agata Murawska
instance Rpc RpcCallNodeInfo RpcResultNodeInfo where
387 47163f0f Agata Murawska
  rpcResultFill _ res =
388 7328a28c Agata Murawska
    fromJSValueToRes res (\(b, vg, hv) -> RpcResultNodeInfo b vg hv)
389 dc623a95 Agata Murawska
390 de2a5704 Iustin Pop
-- ** Version
391 de2a5704 Iustin Pop
392 08f7d24d Iustin Pop
-- | Query node version.
393 08f7d24d Iustin Pop
$(buildObject "RpcCallVersion" "rpcCallVersion" [])
394 8779d21a Agata Murawska
395 08f7d24d Iustin Pop
-- | Query node reply.
396 8779d21a Agata Murawska
$(buildObject "RpcResultVersion" "rpcResultVersion"
397 8779d21a Agata Murawska
  [ simpleField "version" [t| Int |]
398 8779d21a Agata Murawska
  ])
399 8779d21a Agata Murawska
400 8779d21a Agata Murawska
instance RpcCall RpcCallVersion where
401 274366e5 Agata Murawska
  rpcCallName _          = "version"
402 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Urgent
403 8779d21a Agata Murawska
  rpcCallAcceptOffline _ = True
404 ff8f0049 Iustin Pop
  rpcCallData _          = J.encode
405 8779d21a Agata Murawska
406 47163f0f Agata Murawska
instance Rpc RpcCallVersion RpcResultVersion where
407 7328a28c Agata Murawska
  rpcResultFill _ res = fromJSValueToRes res RpcResultVersion
408 8779d21a Agata Murawska
409 de2a5704 Iustin Pop
-- ** StorageList
410 de2a5704 Iustin Pop
411 47163f0f Agata Murawska
$(buildObject "RpcCallStorageList" "rpcCallStorageList"
412 47163f0f Agata Murawska
  [ simpleField "su_name" [t| StorageType |]
413 47163f0f Agata Murawska
  , simpleField "su_args" [t| [String] |]
414 47163f0f Agata Murawska
  , simpleField "name"    [t| String |]
415 47163f0f Agata Murawska
  , simpleField "fields"  [t| [StorageField] |]
416 47163f0f Agata Murawska
  ])
417 47163f0f Agata Murawska
418 47163f0f Agata Murawska
-- FIXME: The resulting JSValues should have types appropriate for their
419 47163f0f Agata Murawska
-- StorageField value: Used -> Bool, Name -> String etc
420 47163f0f Agata Murawska
$(buildObject "RpcResultStorageList" "rpcResStorageList"
421 47163f0f Agata Murawska
  [ simpleField "storage" [t| [[(StorageField, J.JSValue)]] |] ])
422 47163f0f Agata Murawska
423 47163f0f Agata Murawska
instance RpcCall RpcCallStorageList where
424 274366e5 Agata Murawska
  rpcCallName _          = "storage_list"
425 274366e5 Agata Murawska
  rpcCallTimeout _       = rpcTimeoutToRaw Normal
426 47163f0f Agata Murawska
  rpcCallAcceptOffline _ = False
427 274366e5 Agata Murawska
  rpcCallData _ call     = J.encode
428 47163f0f Agata Murawska
    ( rpcCallStorageListSuName call
429 47163f0f Agata Murawska
    , rpcCallStorageListSuArgs call
430 47163f0f Agata Murawska
    , rpcCallStorageListName call
431 47163f0f Agata Murawska
    , rpcCallStorageListFields call
432 47163f0f Agata Murawska
    )
433 47163f0f Agata Murawska
434 47163f0f Agata Murawska
instance Rpc RpcCallStorageList RpcResultStorageList where
435 47163f0f Agata Murawska
  rpcResultFill call res =
436 47163f0f Agata Murawska
    let sfields = rpcCallStorageListFields call in
437 7328a28c Agata Murawska
    fromJSValueToRes res (RpcResultStorageList . map (zip sfields))
438 de2a5704 Iustin Pop
439 de2a5704 Iustin Pop
-- ** TestDelay
440 de2a5704 Iustin Pop
441 de2a5704 Iustin Pop
-- | Call definition for test delay.
442 de2a5704 Iustin Pop
$(buildObject "RpcCallTestDelay" "rpcCallTestDelay"
443 de2a5704 Iustin Pop
  [ simpleField "duration" [t| Double |]
444 de2a5704 Iustin Pop
  ])
445 de2a5704 Iustin Pop
446 de2a5704 Iustin Pop
-- | Result definition for test delay.
447 de2a5704 Iustin Pop
data RpcResultTestDelay = RpcResultTestDelay
448 de2a5704 Iustin Pop
                          deriving Show
449 de2a5704 Iustin Pop
450 de2a5704 Iustin Pop
-- | Custom JSON instance for null result.
451 de2a5704 Iustin Pop
instance J.JSON RpcResultTestDelay where
452 de2a5704 Iustin Pop
  showJSON _        = J.JSNull
453 de2a5704 Iustin Pop
  readJSON J.JSNull = return RpcResultTestDelay
454 de2a5704 Iustin Pop
  readJSON _        = fail "Unable to read RpcResultTestDelay"
455 de2a5704 Iustin Pop
456 de2a5704 Iustin Pop
instance RpcCall RpcCallTestDelay where
457 de2a5704 Iustin Pop
  rpcCallName _          = "test_delay"
458 de2a5704 Iustin Pop
  rpcCallTimeout         = ceiling . (+ 5) . rpcCallTestDelayDuration
459 de2a5704 Iustin Pop
  rpcCallAcceptOffline _ = False
460 de2a5704 Iustin Pop
  rpcCallData _ call     = J.encode [rpcCallTestDelayDuration call]
461 de2a5704 Iustin Pop
462 de2a5704 Iustin Pop
instance Rpc RpcCallTestDelay RpcResultTestDelay where
463 de2a5704 Iustin Pop
  rpcResultFill _ res = fromJSValueToRes res id
464 842515dd Iustin Pop
465 842515dd Iustin Pop
-- ** ExportList
466 842515dd Iustin Pop
467 842515dd Iustin Pop
-- | Call definition for export list.
468 842515dd Iustin Pop
469 842515dd Iustin Pop
$(buildObject "RpcCallExportList" "rpcCallExportList" [])
470 842515dd Iustin Pop
471 842515dd Iustin Pop
-- | Result definition for export list.
472 842515dd Iustin Pop
$(buildObject "RpcResultExportList" "rpcResExportList"
473 842515dd Iustin Pop
  [ simpleField "exports" [t| [String] |]
474 842515dd Iustin Pop
  ])
475 842515dd Iustin Pop
476 842515dd Iustin Pop
instance RpcCall RpcCallExportList where
477 842515dd Iustin Pop
  rpcCallName _          = "export_list"
478 842515dd Iustin Pop
  rpcCallTimeout _       = rpcTimeoutToRaw Fast
479 842515dd Iustin Pop
  rpcCallAcceptOffline _ = False
480 842515dd Iustin Pop
  rpcCallData _          = J.encode
481 842515dd Iustin Pop
482 842515dd Iustin Pop
instance Rpc RpcCallExportList RpcResultExportList where
483 842515dd Iustin Pop
  rpcResultFill _ res = fromJSValueToRes res RpcResultExportList