Revision 599239ad htools/Ganeti/Rpc.hs
b/htools/Ganeti/Rpc.hs | ||
---|---|---|
31 | 31 |
, RpcResult |
32 | 32 |
, Rpc |
33 | 33 |
, RpcError(..) |
34 |
, ERpcError |
|
34 | 35 |
, executeRpcCall |
35 | 36 |
|
36 | 37 |
, rpcCallName |
... | ... | |
105 | 106 |
show (OfflineNodeError node) = |
106 | 107 |
"Node " ++ nodeName node ++ " is marked as offline" |
107 | 108 |
|
108 |
rpcErrorJsonReport :: (Monad m) => J.Result a -> m (Either RpcError a) |
|
109 |
type ERpcError = Either RpcError |
|
110 |
|
|
111 |
rpcErrorJsonReport :: (Monad m) => J.Result a -> m (ERpcError a) |
|
109 | 112 |
rpcErrorJsonReport (J.Error x) = return . Left $ JsonDecodeError x |
110 | 113 |
rpcErrorJsonReport (J.Ok x) = return $ Right x |
111 | 114 |
|
... | ... | |
135 | 138 |
-- | A generic class for RPC results with default implementation. |
136 | 139 |
class (J.JSON a) => RpcResult a where |
137 | 140 |
-- | Create a result based on the received HTTP response. |
138 |
rpcResultFill :: (Monad m) => String -> m (Either RpcError a)
|
|
141 |
rpcResultFill :: (Monad m) => String -> m (ERpcError a) |
|
139 | 142 |
|
140 | 143 |
rpcResultFill res = rpcErrorJsonReport $ J.decode res |
141 | 144 |
|
... | ... | |
152 | 155 |
|
153 | 156 |
-- | Execute the request and return the result as a plain String. When |
154 | 157 |
-- curl reports an error, we propagate it. |
155 |
executeHttpRequest :: Node -> Either RpcError HttpClientRequest
|
|
156 |
-> IO (Either RpcError String)
|
|
158 |
executeHttpRequest :: Node -> ERpcError HttpClientRequest |
|
159 |
-> IO (ERpcError String) |
|
157 | 160 |
|
158 | 161 |
executeHttpRequest _ (Left rpc_err) = return $ Left rpc_err |
159 | 162 |
#ifdef NO_CURL |
... | ... | |
182 | 185 |
-- | Create HTTP request for a given node provided it is online, |
183 | 186 |
-- otherwise create empty response. |
184 | 187 |
prepareHttpRequest :: (RpcCall a) => Node -> a |
185 |
-> Either RpcError HttpClientRequest
|
|
188 |
-> ERpcError HttpClientRequest |
|
186 | 189 |
prepareHttpRequest node call |
187 | 190 |
| rpcCallAcceptOffline call || not (nodeOffline node) = |
188 | 191 |
Right HttpClientRequest { requestTimeout = rpcCallTimeout call |
... | ... | |
192 | 195 |
| otherwise = Left $ OfflineNodeError node |
193 | 196 |
|
194 | 197 |
-- | Parse the response or propagate the error. |
195 |
parseHttpResponse :: (Monad m, RpcResult a) => Either RpcError String
|
|
196 |
-> m (Either RpcError a)
|
|
198 |
parseHttpResponse :: (Monad m, RpcResult a) => ERpcError String |
|
199 |
-> m (ERpcError a) |
|
197 | 200 |
parseHttpResponse (Left err) = return $ Left err |
198 | 201 |
parseHttpResponse (Right response) = rpcResultFill response |
199 | 202 |
|
200 | 203 |
-- | Execute RPC call for a sigle node. |
201 |
executeSingleRpcCall :: (Rpc a b) => Node -> a -> IO (Node, Either RpcError b)
|
|
204 |
executeSingleRpcCall :: (Rpc a b) => Node -> a -> IO (Node, ERpcError b) |
|
202 | 205 |
executeSingleRpcCall node call = do |
203 | 206 |
let request = prepareHttpRequest node call |
204 | 207 |
response <- executeHttpRequest node request |
... | ... | |
206 | 209 |
return (node, result) |
207 | 210 |
|
208 | 211 |
-- | Execute RPC call for many nodes in parallel. |
209 |
executeRpcCall :: (Rpc a b) => [Node] -> a -> IO [(Node, Either RpcError b)]
|
|
212 |
executeRpcCall :: (Rpc a b) => [Node] -> a -> IO [(Node, ERpcError b)] |
|
210 | 213 |
executeRpcCall nodes call = |
211 | 214 |
sequence $ parMap rwhnf (uncurry executeSingleRpcCall) |
212 | 215 |
(zip nodes $ repeat call) |
Also available in: Unified diff