Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Rpc.hs @ ccf17aa3

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