root / htools / Ganeti / Rpc.hs @ d4709cce
History | View | Annotate | Download (2.6 kB)
1 |
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} |
---|---|
2 |
|
3 |
{-| Implementation of the RPC client. |
4 |
|
5 |
-} |
6 |
|
7 |
{- |
8 |
|
9 |
Copyright (C) 2012 Google Inc. |
10 |
|
11 |
This program is free software; you can redistribute it and/or modify |
12 |
it under the terms of the GNU General Public License as published by |
13 |
the Free Software Foundation; either version 2 of the License, or |
14 |
(at your option) any later version. |
15 |
|
16 |
This program is distributed in the hope that it will be useful, but |
17 |
WITHOUT ANY WARRANTY; without even the implied warranty of |
18 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 |
General Public License for more details. |
20 |
|
21 |
You should have received a copy of the GNU General Public License |
22 |
along with this program; if not, write to the Free Software |
23 |
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
24 |
02110-1301, USA. |
25 |
|
26 |
-} |
27 |
|
28 |
module Ganeti.Rpc |
29 |
( RpcCall |
30 |
, RpcResult |
31 |
, Rpc |
32 |
, RpcError(..) |
33 |
|
34 |
, rpcCallName |
35 |
, rpcCallTimeout |
36 |
, rpcCallData |
37 |
, rpcCallAcceptOffline |
38 |
|
39 |
, rpcResultFill |
40 |
) where |
41 |
|
42 |
import qualified Text.JSON as J |
43 |
|
44 |
import Ganeti.Objects |
45 |
|
46 |
-- | Data type for RPC error reporting. |
47 |
data RpcError |
48 |
= CurlDisabledError |
49 |
| CurlLayerError Node String |
50 |
| JsonDecodeError String |
51 |
| OfflineNodeError Node |
52 |
deriving Eq |
53 |
|
54 |
instance Show RpcError where |
55 |
show CurlDisabledError = |
56 |
"RPC/curl backend disabled at compile time" |
57 |
show (CurlLayerError node code) = |
58 |
"Curl error for " ++ nodeName node ++ ", error " ++ code |
59 |
show (JsonDecodeError msg) = |
60 |
"Error while decoding JSON from HTTP response " ++ msg |
61 |
show (OfflineNodeError node) = |
62 |
"Node " ++ nodeName node ++ " is marked as offline" |
63 |
|
64 |
rpcErrorJsonReport :: (Monad m) => J.Result a -> m (Either RpcError a) |
65 |
rpcErrorJsonReport (J.Error x) = return $ Left $ JsonDecodeError x |
66 |
rpcErrorJsonReport (J.Ok x) = return $ Right x |
67 |
|
68 |
-- | A generic class for RPC calls. |
69 |
class (J.JSON a) => RpcCall a where |
70 |
-- | Give the (Python) name of the procedure. |
71 |
rpcCallName :: a -> String |
72 |
-- | Calculate the timeout value for the call execution. |
73 |
rpcCallTimeout :: a -> Int |
74 |
-- | Prepare arguments of the call to be send as POST. |
75 |
rpcCallData :: Node -> a -> String |
76 |
-- | Whether we accept offline nodes when making a call. |
77 |
rpcCallAcceptOffline :: a -> Bool |
78 |
|
79 |
rpcCallData _ = J.encode |
80 |
|
81 |
-- | A generic class for RPC results with default implementation. |
82 |
class (J.JSON a) => RpcResult a where |
83 |
-- | Create a result based on the received HTTP response. |
84 |
rpcResultFill :: (Monad m) => String -> m (Either RpcError a) |
85 |
|
86 |
rpcResultFill res = rpcErrorJsonReport $ J.decode res |
87 |
|
88 |
-- | Generic class that ensures matching RPC call with its respective |
89 |
-- result. |
90 |
class (RpcCall a, RpcResult b) => Rpc a b | a -> b |